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 * http://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.charset.Charset; 021import java.text.Normalizer; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.HashSet; 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; 032 033/** 034 * <p>Operations on {@link java.lang.String} that are 035 * {@code null} safe.</p> 036 * 037 * <ul> 038 * <li><b>IsEmpty/IsBlank</b> 039 * - checks if a String contains text</li> 040 * <li><b>Trim/Strip</b> 041 * - removes leading and trailing whitespace</li> 042 * <li><b>Equals/Compare</b> 043 * - compares two strings in a null-safe manner</li> 044 * <li><b>startsWith</b> 045 * - check if a String starts with a prefix in a null-safe manner</li> 046 * <li><b>endsWith</b> 047 * - check if a String ends with a suffix in a null-safe manner</li> 048 * <li><b>IndexOf/LastIndexOf/Contains</b> 049 * - null-safe index-of checks 050 * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b> 051 * - index-of any of a set of Strings</li> 052 * <li><b>ContainsOnly/ContainsNone/ContainsAny</b> 053 * - checks if String contains only/none/any of these characters</li> 054 * <li><b>Substring/Left/Right/Mid</b> 055 * - null-safe substring extractions</li> 056 * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b> 057 * - substring extraction relative to other strings</li> 058 * <li><b>Split/Join</b> 059 * - splits a String into an array of substrings and vice versa</li> 060 * <li><b>Remove/Delete</b> 061 * - removes part of a String</li> 062 * <li><b>Replace/Overlay</b> 063 * - Searches a String and replaces one String with another</li> 064 * <li><b>Chomp/Chop</b> 065 * - removes the last part of a String</li> 066 * <li><b>AppendIfMissing</b> 067 * - appends a suffix to the end of the String if not present</li> 068 * <li><b>PrependIfMissing</b> 069 * - prepends a prefix to the start of the String if not present</li> 070 * <li><b>LeftPad/RightPad/Center/Repeat</b> 071 * - pads a String</li> 072 * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b> 073 * - changes the case of a String</li> 074 * <li><b>CountMatches</b> 075 * - counts the number of occurrences of one String in another</li> 076 * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b> 077 * - checks the characters in a String</li> 078 * <li><b>DefaultString</b> 079 * - protects against a null input String</li> 080 * <li><b>Rotate</b> 081 * - rotate (circular shift) a String</li> 082 * <li><b>Reverse/ReverseDelimited</b> 083 * - reverses a String</li> 084 * <li><b>Abbreviate</b> 085 * - abbreviates a string using ellipses or another given String</li> 086 * <li><b>Difference</b> 087 * - compares Strings and reports on their differences</li> 088 * <li><b>LevenshteinDistance</b> 089 * - the number of changes needed to change one String into another</li> 090 * </ul> 091 * 092 * <p>The {@code StringUtils} class defines certain words related to 093 * String handling.</p> 094 * 095 * <ul> 096 * <li>null - {@code null}</li> 097 * <li>empty - a zero-length string ({@code ""})</li> 098 * <li>space - the space character ({@code ' '}, char 32)</li> 099 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> 100 * <li>trim - the characters <= 32 as in {@link String#trim()}</li> 101 * </ul> 102 * 103 * <p>{@code StringUtils} handles {@code null} input Strings quietly. 104 * That is to say that a {@code null} input will return {@code null}. 105 * Where a {@code boolean} or {@code int} is being returned 106 * details vary by method.</p> 107 * 108 * <p>A side effect of the {@code null} handling is that a 109 * {@code NullPointerException} should be considered a bug in 110 * {@code StringUtils}.</p> 111 * 112 * <p>Methods in this class include sample code in their Javadoc comments to explain their operation. 113 * The symbol {@code *} is used to indicate any input including {@code null}.</p> 114 * 115 * <p>#ThreadSafe#</p> 116 * @see java.lang.String 117 * @since 1.0 118 */ 119//@Immutable 120public class StringUtils { 121 122 private static final int STRING_BUILDER_SIZE = 256; 123 124 // Performance testing notes (JDK 1.4, Jul03, scolebourne) 125 // Whitespace: 126 // Character.isWhitespace() is faster than WHITESPACE.indexOf() 127 // where WHITESPACE is a string of all whitespace characters 128 // 129 // Character access: 130 // String.charAt(n) versus toCharArray(), then array[n] 131 // String.charAt(n) is about 15% worse for a 10K string 132 // They are about equal for a length 50 string 133 // String.charAt(n) is about 4 times better for a length 3 string 134 // String.charAt(n) is best bet overall 135 // 136 // Append: 137 // String.concat about twice as fast as StringBuffer.append 138 // (not sure who tested this) 139 140 /** 141 * A String for a space character. 142 * 143 * @since 3.2 144 */ 145 public static final String SPACE = " "; 146 147 /** 148 * The empty String {@code ""}. 149 * @since 2.0 150 */ 151 public static final String EMPTY = ""; 152 153 /** 154 * A String for linefeed LF ("\n"). 155 * 156 * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 157 * for Character and String Literals</a> 158 * @since 3.2 159 */ 160 public static final String LF = "\n"; 161 162 /** 163 * A String for carriage return CR ("\r"). 164 * 165 * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 166 * for Character and String Literals</a> 167 * @since 3.2 168 */ 169 public static final String CR = "\r"; 170 171 /** 172 * Represents a failed index search. 173 * @since 2.1 174 */ 175 public static final int INDEX_NOT_FOUND = -1; 176 177 /** 178 * <p>The maximum size to which the padding constant(s) can expand.</p> 179 */ 180 private static final int PAD_LIMIT = 8192; 181 182 /** 183 * Pattern used in {@link #stripAccents(String)}. 184 */ 185 private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$ 186 187 // Abbreviating 188 //----------------------------------------------------------------------- 189 /** 190 * <p>Abbreviates a String using ellipses. This will turn 191 * "Now is the time for all good men" into "Now is the time for..."</p> 192 * 193 * <p>Specifically:</p> 194 * <ul> 195 * <li>If the number of characters in {@code str} is less than or equal to 196 * {@code maxWidth}, return {@code str}.</li> 197 * <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li> 198 * <li>If {@code maxWidth} is less than {@code 4}, throw an 199 * {@code IllegalArgumentException}.</li> 200 * <li>In no case will it return a String of length greater than 201 * {@code maxWidth}.</li> 202 * </ul> 203 * 204 * <pre> 205 * StringUtils.abbreviate(null, *) = null 206 * StringUtils.abbreviate("", 4) = "" 207 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 208 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 209 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 210 * StringUtils.abbreviate("abcdefg", 4) = "a..." 211 * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException 212 * </pre> 213 * 214 * @param str the String to check, may be null 215 * @param maxWidth maximum length of result String, must be at least 4 216 * @return abbreviated String, {@code null} if null String input 217 * @throws IllegalArgumentException if the width is too small 218 * @since 2.0 219 */ 220 public static String abbreviate(final String str, final int maxWidth) { 221 return abbreviate(str, "...", 0, maxWidth); 222 } 223 224 /** 225 * <p>Abbreviates a String using ellipses. This will turn 226 * "Now is the time for all good men" into "...is the time for..."</p> 227 * 228 * <p>Works like {@code abbreviate(String, int)}, but allows you to specify 229 * a "left edge" offset. Note that this left edge is not necessarily going to 230 * be the leftmost character in the result, or the first character following the 231 * ellipses, but it will appear somewhere in the result. 232 * 233 * <p>In no case will it return a String of length greater than 234 * {@code maxWidth}.</p> 235 * 236 * <pre> 237 * StringUtils.abbreviate(null, *, *) = null 238 * StringUtils.abbreviate("", 0, 4) = "" 239 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 240 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 241 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 242 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 243 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 244 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 245 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 246 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 247 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 248 * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException 249 * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException 250 * </pre> 251 * 252 * @param str the String to check, may be null 253 * @param offset left edge of source String 254 * @param maxWidth maximum length of result String, must be at least 4 255 * @return abbreviated String, {@code null} if null String input 256 * @throws IllegalArgumentException if the width is too small 257 * @since 2.0 258 */ 259 public static String abbreviate(final String str, final int offset, final int maxWidth) { 260 return abbreviate(str, "...", offset, maxWidth); 261 } 262 263 /** 264 * <p>Abbreviates a String using another given String as replacement marker. This will turn 265 * "Now is the time for all good men" into "Now is the time for..." if "..." was defined 266 * as the replacement marker.</p> 267 * 268 * <p>Specifically:</p> 269 * <ul> 270 * <li>If the number of characters in {@code str} is less than or equal to 271 * {@code maxWidth}, return {@code str}.</li> 272 * <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li> 273 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an 274 * {@code IllegalArgumentException}.</li> 275 * <li>In no case will it return a String of length greater than 276 * {@code maxWidth}.</li> 277 * </ul> 278 * 279 * <pre> 280 * StringUtils.abbreviate(null, "...", *) = null 281 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg" 282 * StringUtils.abbreviate("", "...", 4) = "" 283 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd." 284 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg" 285 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg" 286 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.." 287 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 288 * StringUtils.abbreviate("abcdefg", "..", 2) = IllegalArgumentException 289 * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException 290 * </pre> 291 * 292 * @param str the String to check, may be null 293 * @param abbrevMarker the String used as replacement marker 294 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1} 295 * @return abbreviated String, {@code null} if null String input 296 * @throws IllegalArgumentException if the width is too small 297 * @since 3.6 298 */ 299 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) { 300 return abbreviate(str, abbrevMarker, 0, maxWidth); 301 } 302 /** 303 * <p>Abbreviates a String using a given replacement marker. This will turn 304 * "Now is the time for all good men" into "...is the time for..." if "..." was defined 305 * as the replacement marker.</p> 306 * 307 * <p>Works like {@code abbreviate(String, String, int)}, but allows you to specify 308 * a "left edge" offset. Note that this left edge is not necessarily going to 309 * be the leftmost character in the result, or the first character following the 310 * replacement marker, but it will appear somewhere in the result. 311 * 312 * <p>In no case will it return a String of length greater than {@code maxWidth}.</p> 313 * 314 * <pre> 315 * StringUtils.abbreviate(null, null, *, *) = null 316 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno" 317 * StringUtils.abbreviate("", "...", 0, 4) = "" 318 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---" 319 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi," 320 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi," 321 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi," 322 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::" 323 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..." 324 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno" 325 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno" 326 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno" 327 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = IllegalArgumentException 328 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = IllegalArgumentException 329 * </pre> 330 * 331 * @param str the String to check, may be null 332 * @param abbrevMarker the String used as replacement marker 333 * @param offset left edge of source String 334 * @param maxWidth maximum length of result String, must be at least 4 335 * @return abbreviated String, {@code null} if null String input 336 * @throws IllegalArgumentException if the width is too small 337 * @since 3.6 338 */ 339 public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) { 340 if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) { 341 return substring(str, 0, maxWidth); 342 } else if (isAnyEmpty(str, abbrevMarker)) { 343 return str; 344 } 345 final int abbrevMarkerLength = abbrevMarker.length(); 346 final int minAbbrevWidth = abbrevMarkerLength + 1; 347 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1; 348 349 if (maxWidth < minAbbrevWidth) { 350 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth)); 351 } 352 if (str.length() <= maxWidth) { 353 return str; 354 } 355 if (offset > str.length()) { 356 offset = str.length(); 357 } 358 if (str.length() - offset < maxWidth - abbrevMarkerLength) { 359 offset = str.length() - (maxWidth - abbrevMarkerLength); 360 } 361 if (offset <= abbrevMarkerLength+1) { 362 return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker; 363 } 364 if (maxWidth < minAbbrevWidthOffset) { 365 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset)); 366 } 367 if (offset + maxWidth - abbrevMarkerLength < str.length()) { 368 return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength); 369 } 370 return abbrevMarker + str.substring(str.length() - (maxWidth - abbrevMarkerLength)); 371 } 372 373 /** 374 * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied 375 * replacement String.</p> 376 * 377 * <p>This abbreviation only occurs if the following criteria is met:</p> 378 * <ul> 379 * <li>Neither the String for abbreviation nor the replacement String are null or empty </li> 380 * <li>The length to truncate to is less than the length of the supplied String</li> 381 * <li>The length to truncate to is greater than 0</li> 382 * <li>The abbreviated String will have enough room for the length supplied replacement String 383 * and the first and last characters of the supplied String for abbreviation</li> 384 * </ul> 385 * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation. 386 * </p> 387 * 388 * <pre> 389 * StringUtils.abbreviateMiddle(null, null, 0) = null 390 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 391 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 392 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 393 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 394 * </pre> 395 * 396 * @param str the String to abbreviate, may be null 397 * @param middle the String to replace the middle characters with, may be null 398 * @param length the length to abbreviate {@code str} to. 399 * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 400 * @since 2.5 401 */ 402 public static String abbreviateMiddle(final String str, final String middle, final int length) { 403 if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length()+2) { 404 return str; 405 } 406 407 final int targetSting = length-middle.length(); 408 final int startOffset = targetSting/2+targetSting%2; 409 final int endOffset = str.length()-targetSting/2; 410 411 return str.substring(0, startOffset) + 412 middle + 413 str.substring(endOffset); 414 } 415 416 /** 417 * Appends the suffix to the end of the string if the string does not 418 * already end with the suffix. 419 * 420 * @param str The string. 421 * @param suffix The suffix to append to the end of the string. 422 * @param ignoreCase Indicates whether the compare should ignore case. 423 * @param suffixes Additional suffixes that are valid terminators (optional). 424 * 425 * @return A new String if suffix was appended, the same string otherwise. 426 */ 427 private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) { 428 if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) { 429 return str; 430 } 431 if (ArrayUtils.isNotEmpty(suffixes)) { 432 for (final CharSequence s : suffixes) { 433 if (endsWith(str, s, ignoreCase)) { 434 return str; 435 } 436 } 437 } 438 return str + suffix.toString(); 439 } 440 441 /** 442 * Appends the suffix to the end of the string if the string does not 443 * already end with any of the suffixes. 444 * 445 * <pre> 446 * StringUtils.appendIfMissing(null, null) = null 447 * StringUtils.appendIfMissing("abc", null) = "abc" 448 * StringUtils.appendIfMissing("", "xyz") = "xyz" 449 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 450 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 451 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 452 * </pre> 453 * <p>With additional suffixes,</p> 454 * <pre> 455 * StringUtils.appendIfMissing(null, null, null) = null 456 * StringUtils.appendIfMissing("abc", null, null) = "abc" 457 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 458 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 459 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 460 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 461 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 462 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 463 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 464 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 465 * </pre> 466 * 467 * @param str The string. 468 * @param suffix The suffix to append to the end of the string. 469 * @param suffixes Additional suffixes that are valid terminators. 470 * 471 * @return A new String if suffix was appended, the same string otherwise. 472 * 473 * @since 3.2 474 */ 475 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 476 return appendIfMissing(str, suffix, false, suffixes); 477 } 478 479 /** 480 * Appends the suffix to the end of the string if the string does not 481 * already end, case insensitive, with any of the suffixes. 482 * 483 * <pre> 484 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 485 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 486 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 487 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 488 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 489 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 490 * </pre> 491 * <p>With additional suffixes,</p> 492 * <pre> 493 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 494 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 495 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 496 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 497 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 498 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz" 499 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 500 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 501 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 502 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 503 * </pre> 504 * 505 * @param str The string. 506 * @param suffix The suffix to append to the end of the string. 507 * @param suffixes Additional suffixes that are valid terminators. 508 * 509 * @return A new String if suffix was appended, the same string otherwise. 510 * 511 * @since 3.2 512 */ 513 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 514 return appendIfMissing(str, suffix, true, suffixes); 515 } 516 517 /** 518 * <p>Capitalizes a String changing the first character to title case as 519 * per {@link Character#toTitleCase(int)}. No other characters are changed.</p> 520 * 521 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}. 522 * A {@code null} input String returns {@code null}.</p> 523 * 524 * <pre> 525 * StringUtils.capitalize(null) = null 526 * StringUtils.capitalize("") = "" 527 * StringUtils.capitalize("cat") = "Cat" 528 * StringUtils.capitalize("cAt") = "CAt" 529 * StringUtils.capitalize("'cat'") = "'cat'" 530 * </pre> 531 * 532 * @param str the String to capitalize, may be null 533 * @return the capitalized String, {@code null} if null String input 534 * @see org.apache.commons.lang3.text.WordUtils#capitalize(String) 535 * @see #uncapitalize(String) 536 * @since 2.0 537 */ 538 public static String capitalize(final String str) { 539 final int strLen = length(str); 540 if (strLen == 0) { 541 return str; 542 } 543 544 final int firstCodepoint = str.codePointAt(0); 545 final int newCodePoint = Character.toTitleCase(firstCodepoint); 546 if (firstCodepoint == newCodePoint) { 547 // already capitalized 548 return str; 549 } 550 551 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 552 int outOffset = 0; 553 newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint 554 for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) { 555 final int codepoint = str.codePointAt(inOffset); 556 newCodePoints[outOffset++] = codepoint; // copy the remaining ones 557 inOffset += Character.charCount(codepoint); 558 } 559 return new String(newCodePoints, 0, outOffset); 560 } 561 562 // Centering 563 //----------------------------------------------------------------------- 564 /** 565 * <p>Centers a String in a larger String of size {@code size} 566 * using the space character (' ').</p> 567 * 568 * <p>If the size is less than the String length, the original String is returned. 569 * A {@code null} String returns {@code null}. 570 * A negative size is treated as zero.</p> 571 * 572 * <p>Equivalent to {@code center(str, size, " ")}.</p> 573 * 574 * <pre> 575 * StringUtils.center(null, *) = null 576 * StringUtils.center("", 4) = " " 577 * StringUtils.center("ab", -1) = "ab" 578 * StringUtils.center("ab", 4) = " ab " 579 * StringUtils.center("abcd", 2) = "abcd" 580 * StringUtils.center("a", 4) = " a " 581 * </pre> 582 * 583 * @param str the String to center, may be null 584 * @param size the int size of new String, negative treated as zero 585 * @return centered String, {@code null} if null String input 586 */ 587 public static String center(final String str, final int size) { 588 return center(str, size, ' '); 589 } 590 591 /** 592 * <p>Centers a String in a larger String of size {@code size}. 593 * Uses a supplied character as the value to pad the String with.</p> 594 * 595 * <p>If the size is less than the String length, the String is returned. 596 * A {@code null} String returns {@code null}. 597 * A negative size is treated as zero.</p> 598 * 599 * <pre> 600 * StringUtils.center(null, *, *) = null 601 * StringUtils.center("", 4, ' ') = " " 602 * StringUtils.center("ab", -1, ' ') = "ab" 603 * StringUtils.center("ab", 4, ' ') = " ab " 604 * StringUtils.center("abcd", 2, ' ') = "abcd" 605 * StringUtils.center("a", 4, ' ') = " a " 606 * StringUtils.center("a", 4, 'y') = "yayy" 607 * </pre> 608 * 609 * @param str the String to center, may be null 610 * @param size the int size of new String, negative treated as zero 611 * @param padChar the character to pad the new String with 612 * @return centered String, {@code null} if null String input 613 * @since 2.0 614 */ 615 public static String center(String str, final int size, final char padChar) { 616 if (str == null || size <= 0) { 617 return str; 618 } 619 final int strLen = str.length(); 620 final int pads = size - strLen; 621 if (pads <= 0) { 622 return str; 623 } 624 str = leftPad(str, strLen + pads / 2, padChar); 625 str = rightPad(str, size, padChar); 626 return str; 627 } 628 629 /** 630 * <p>Centers a String in a larger String of size {@code size}. 631 * Uses a supplied String as the value to pad the String with.</p> 632 * 633 * <p>If the size is less than the String length, the String is returned. 634 * A {@code null} String returns {@code null}. 635 * A negative size is treated as zero.</p> 636 * 637 * <pre> 638 * StringUtils.center(null, *, *) = null 639 * StringUtils.center("", 4, " ") = " " 640 * StringUtils.center("ab", -1, " ") = "ab" 641 * StringUtils.center("ab", 4, " ") = " ab " 642 * StringUtils.center("abcd", 2, " ") = "abcd" 643 * StringUtils.center("a", 4, " ") = " a " 644 * StringUtils.center("a", 4, "yz") = "yayz" 645 * StringUtils.center("abc", 7, null) = " abc " 646 * StringUtils.center("abc", 7, "") = " abc " 647 * </pre> 648 * 649 * @param str the String to center, may be null 650 * @param size the int size of new String, negative treated as zero 651 * @param padStr the String to pad the new String with, must not be null or empty 652 * @return centered String, {@code null} if null String input 653 * @throws IllegalArgumentException if padStr is {@code null} or empty 654 */ 655 public static String center(String str, final int size, String padStr) { 656 if (str == null || size <= 0) { 657 return str; 658 } 659 if (isEmpty(padStr)) { 660 padStr = SPACE; 661 } 662 final int strLen = str.length(); 663 final int pads = size - strLen; 664 if (pads <= 0) { 665 return str; 666 } 667 str = leftPad(str, strLen + pads / 2, padStr); 668 str = rightPad(str, size, padStr); 669 return str; 670 } 671 672 // Chomping 673 //----------------------------------------------------------------------- 674 /** 675 * <p>Removes one newline from end of a String if it's there, 676 * otherwise leave it alone. A newline is "{@code \n}", 677 * "{@code \r}", or "{@code \r\n}".</p> 678 * 679 * <p>NOTE: This method changed in 2.0. 680 * It now more closely matches Perl chomp.</p> 681 * 682 * <pre> 683 * StringUtils.chomp(null) = null 684 * StringUtils.chomp("") = "" 685 * StringUtils.chomp("abc \r") = "abc " 686 * StringUtils.chomp("abc\n") = "abc" 687 * StringUtils.chomp("abc\r\n") = "abc" 688 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 689 * StringUtils.chomp("abc\n\r") = "abc\n" 690 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 691 * StringUtils.chomp("\r") = "" 692 * StringUtils.chomp("\n") = "" 693 * StringUtils.chomp("\r\n") = "" 694 * </pre> 695 * 696 * @param str the String to chomp a newline from, may be null 697 * @return String without newline, {@code null} if null String input 698 */ 699 public static String chomp(final String str) { 700 if (isEmpty(str)) { 701 return str; 702 } 703 704 if (str.length() == 1) { 705 final char ch = str.charAt(0); 706 if (ch == CharUtils.CR || ch == CharUtils.LF) { 707 return EMPTY; 708 } 709 return str; 710 } 711 712 int lastIdx = str.length() - 1; 713 final char last = str.charAt(lastIdx); 714 715 if (last == CharUtils.LF) { 716 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 717 lastIdx--; 718 } 719 } else if (last != CharUtils.CR) { 720 lastIdx++; 721 } 722 return str.substring(0, lastIdx); 723 } 724 725 /** 726 * <p>Removes {@code separator} from the end of 727 * {@code str} if it's there, otherwise leave it alone.</p> 728 * 729 * <p>NOTE: This method changed in version 2.0. 730 * It now more closely matches Perl chomp. 731 * For the previous behavior, use {@link #substringBeforeLast(String, String)}. 732 * This method uses {@link String#endsWith(String)}.</p> 733 * 734 * <pre> 735 * StringUtils.chomp(null, *) = null 736 * StringUtils.chomp("", *) = "" 737 * StringUtils.chomp("foobar", "bar") = "foo" 738 * StringUtils.chomp("foobar", "baz") = "foobar" 739 * StringUtils.chomp("foo", "foo") = "" 740 * StringUtils.chomp("foo ", "foo") = "foo " 741 * StringUtils.chomp(" foo", "foo") = " " 742 * StringUtils.chomp("foo", "foooo") = "foo" 743 * StringUtils.chomp("foo", "") = "foo" 744 * StringUtils.chomp("foo", null) = "foo" 745 * </pre> 746 * 747 * @param str the String to chomp from, may be null 748 * @param separator separator String, may be null 749 * @return String without trailing separator, {@code null} if null String input 750 * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead 751 */ 752 @Deprecated 753 public static String chomp(final String str, final String separator) { 754 return removeEnd(str, separator); 755 } 756 757 // Chopping 758 //----------------------------------------------------------------------- 759 /** 760 * <p>Remove the last character from a String.</p> 761 * 762 * <p>If the String ends in {@code \r\n}, then remove both 763 * of them.</p> 764 * 765 * <pre> 766 * StringUtils.chop(null) = null 767 * StringUtils.chop("") = "" 768 * StringUtils.chop("abc \r") = "abc " 769 * StringUtils.chop("abc\n") = "abc" 770 * StringUtils.chop("abc\r\n") = "abc" 771 * StringUtils.chop("abc") = "ab" 772 * StringUtils.chop("abc\nabc") = "abc\nab" 773 * StringUtils.chop("a") = "" 774 * StringUtils.chop("\r") = "" 775 * StringUtils.chop("\n") = "" 776 * StringUtils.chop("\r\n") = "" 777 * </pre> 778 * 779 * @param str the String to chop last character from, may be null 780 * @return String without last character, {@code null} if null String input 781 */ 782 public static String chop(final String str) { 783 if (str == null) { 784 return null; 785 } 786 final int strLen = str.length(); 787 if (strLen < 2) { 788 return EMPTY; 789 } 790 final int lastIdx = strLen - 1; 791 final String ret = str.substring(0, lastIdx); 792 final char last = str.charAt(lastIdx); 793 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 794 return ret.substring(0, lastIdx - 1); 795 } 796 return ret; 797 } 798 799 // Compare 800 //----------------------------------------------------------------------- 801 /** 802 * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p> 803 * <ul> 804 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 805 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 806 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 807 * </ul> 808 * 809 * <p>This is a {@code null} safe version of :</p> 810 * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> 811 * 812 * <p>{@code null} value is considered less than non-{@code null} value. 813 * Two {@code null} references are considered equal.</p> 814 * 815 * <pre> 816 * StringUtils.compare(null, null) = 0 817 * StringUtils.compare(null , "a") < 0 818 * StringUtils.compare("a", null) > 0 819 * StringUtils.compare("abc", "abc") = 0 820 * StringUtils.compare("a", "b") < 0 821 * StringUtils.compare("b", "a") > 0 822 * StringUtils.compare("a", "B") > 0 823 * StringUtils.compare("ab", "abc") < 0 824 * </pre> 825 * 826 * @see #compare(String, String, boolean) 827 * @see String#compareTo(String) 828 * @param str1 the String to compare from 829 * @param str2 the String to compare to 830 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2} 831 * @since 3.5 832 */ 833 public static int compare(final String str1, final String str2) { 834 return compare(str1, str2, true); 835 } 836 837 /** 838 * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p> 839 * <ul> 840 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 841 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 842 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 843 * </ul> 844 * 845 * <p>This is a {@code null} safe version of :</p> 846 * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> 847 * 848 * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. 849 * Two {@code null} references are considered equal.</p> 850 * 851 * <pre> 852 * StringUtils.compare(null, null, *) = 0 853 * StringUtils.compare(null , "a", true) < 0 854 * StringUtils.compare(null , "a", false) > 0 855 * StringUtils.compare("a", null, true) > 0 856 * StringUtils.compare("a", null, false) < 0 857 * StringUtils.compare("abc", "abc", *) = 0 858 * StringUtils.compare("a", "b", *) < 0 859 * StringUtils.compare("b", "a", *) > 0 860 * StringUtils.compare("a", "B", *) > 0 861 * StringUtils.compare("ab", "abc", *) < 0 862 * </pre> 863 * 864 * @see String#compareTo(String) 865 * @param str1 the String to compare from 866 * @param str2 the String to compare to 867 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value 868 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2} 869 * @since 3.5 870 */ 871 public static int compare(final String str1, final String str2, final boolean nullIsLess) { 872 if (str1 == str2) { 873 return 0; 874 } 875 if (str1 == null) { 876 return nullIsLess ? -1 : 1; 877 } 878 if (str2 == null) { 879 return nullIsLess ? 1 : - 1; 880 } 881 return str1.compareTo(str2); 882 } 883 884 /** 885 * <p>Compare two Strings lexicographically, ignoring case differences, 886 * as per {@link String#compareToIgnoreCase(String)}, returning :</p> 887 * <ul> 888 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 889 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 890 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 891 * </ul> 892 * 893 * <p>This is a {@code null} safe version of :</p> 894 * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> 895 * 896 * <p>{@code null} value is considered less than non-{@code null} value. 897 * Two {@code null} references are considered equal. 898 * Comparison is case insensitive.</p> 899 * 900 * <pre> 901 * StringUtils.compareIgnoreCase(null, null) = 0 902 * StringUtils.compareIgnoreCase(null , "a") < 0 903 * StringUtils.compareIgnoreCase("a", null) > 0 904 * StringUtils.compareIgnoreCase("abc", "abc") = 0 905 * StringUtils.compareIgnoreCase("abc", "ABC") = 0 906 * StringUtils.compareIgnoreCase("a", "b") < 0 907 * StringUtils.compareIgnoreCase("b", "a") > 0 908 * StringUtils.compareIgnoreCase("a", "B") < 0 909 * StringUtils.compareIgnoreCase("A", "b") < 0 910 * StringUtils.compareIgnoreCase("ab", "ABC") < 0 911 * </pre> 912 * 913 * @see #compareIgnoreCase(String, String, boolean) 914 * @see String#compareToIgnoreCase(String) 915 * @param str1 the String to compare from 916 * @param str2 the String to compare to 917 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, 918 * ignoring case differences. 919 * @since 3.5 920 */ 921 public static int compareIgnoreCase(final String str1, final String str2) { 922 return compareIgnoreCase(str1, str2, true); 923 } 924 925 /** 926 * <p>Compare two Strings lexicographically, ignoring case differences, 927 * as per {@link String#compareToIgnoreCase(String)}, returning :</p> 928 * <ul> 929 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 930 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 931 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 932 * </ul> 933 * 934 * <p>This is a {@code null} safe version of :</p> 935 * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> 936 * 937 * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. 938 * Two {@code null} references are considered equal. 939 * Comparison is case insensitive.</p> 940 * 941 * <pre> 942 * StringUtils.compareIgnoreCase(null, null, *) = 0 943 * StringUtils.compareIgnoreCase(null , "a", true) < 0 944 * StringUtils.compareIgnoreCase(null , "a", false) > 0 945 * StringUtils.compareIgnoreCase("a", null, true) > 0 946 * StringUtils.compareIgnoreCase("a", null, false) < 0 947 * StringUtils.compareIgnoreCase("abc", "abc", *) = 0 948 * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0 949 * StringUtils.compareIgnoreCase("a", "b", *) < 0 950 * StringUtils.compareIgnoreCase("b", "a", *) > 0 951 * StringUtils.compareIgnoreCase("a", "B", *) < 0 952 * StringUtils.compareIgnoreCase("A", "b", *) < 0 953 * StringUtils.compareIgnoreCase("ab", "abc", *) < 0 954 * </pre> 955 * 956 * @see String#compareToIgnoreCase(String) 957 * @param str1 the String to compare from 958 * @param str2 the String to compare to 959 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value 960 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, 961 * ignoring case differences. 962 * @since 3.5 963 */ 964 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { 965 if (str1 == str2) { 966 return 0; 967 } 968 if (str1 == null) { 969 return nullIsLess ? -1 : 1; 970 } 971 if (str2 == null) { 972 return nullIsLess ? 1 : - 1; 973 } 974 return str1.compareToIgnoreCase(str2); 975 } 976 977 /** 978 * <p>Checks if CharSequence contains a search CharSequence, handling {@code null}. 979 * This method uses {@link String#indexOf(String)} if possible.</p> 980 * 981 * <p>A {@code null} CharSequence will return {@code false}.</p> 982 * 983 * <pre> 984 * StringUtils.contains(null, *) = false 985 * StringUtils.contains(*, null) = false 986 * StringUtils.contains("", "") = true 987 * StringUtils.contains("abc", "") = true 988 * StringUtils.contains("abc", "a") = true 989 * StringUtils.contains("abc", "z") = false 990 * </pre> 991 * 992 * @param seq the CharSequence to check, may be null 993 * @param searchSeq the CharSequence to find, may be null 994 * @return true if the CharSequence contains the search CharSequence, 995 * false if not or {@code null} string input 996 * @since 2.0 997 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 998 */ 999 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 1000 if (seq == null || searchSeq == null) { 1001 return false; 1002 } 1003 return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0; 1004 } 1005 1006 // Contains 1007 //----------------------------------------------------------------------- 1008 /** 1009 * <p>Checks if CharSequence contains a search character, handling {@code null}. 1010 * This method uses {@link String#indexOf(int)} if possible.</p> 1011 * 1012 * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p> 1013 * 1014 * <pre> 1015 * StringUtils.contains(null, *) = false 1016 * StringUtils.contains("", *) = false 1017 * StringUtils.contains("abc", 'a') = true 1018 * StringUtils.contains("abc", 'z') = false 1019 * </pre> 1020 * 1021 * @param seq the CharSequence to check, may be null 1022 * @param searchChar the character to find 1023 * @return true if the CharSequence contains the search character, 1024 * false if not or {@code null} string input 1025 * @since 2.0 1026 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1027 */ 1028 public static boolean contains(final CharSequence seq, final int searchChar) { 1029 if (isEmpty(seq)) { 1030 return false; 1031 } 1032 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1033 } 1034 1035 // ContainsAny 1036 //----------------------------------------------------------------------- 1037 /** 1038 * <p>Checks if the CharSequence contains any character in the given 1039 * set of characters.</p> 1040 * 1041 * <p>A {@code null} CharSequence will return {@code false}. 1042 * A {@code null} or zero length search array will return {@code false}.</p> 1043 * 1044 * <pre> 1045 * StringUtils.containsAny(null, *) = false 1046 * StringUtils.containsAny("", *) = false 1047 * StringUtils.containsAny(*, null) = false 1048 * StringUtils.containsAny(*, []) = false 1049 * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true 1050 * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true 1051 * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true 1052 * StringUtils.containsAny("aba", ['z']) = false 1053 * </pre> 1054 * 1055 * @param cs the CharSequence to check, may be null 1056 * @param searchChars the chars to search for, may be null 1057 * @return the {@code true} if any of the chars are found, 1058 * {@code false} if no match or null input 1059 * @since 2.4 1060 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1061 */ 1062 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1063 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1064 return false; 1065 } 1066 final int csLength = cs.length(); 1067 final int searchLength = searchChars.length; 1068 final int csLast = csLength - 1; 1069 final int searchLast = searchLength - 1; 1070 for (int i = 0; i < csLength; i++) { 1071 final char ch = cs.charAt(i); 1072 for (int j = 0; j < searchLength; j++) { 1073 if (searchChars[j] == ch) { 1074 if (Character.isHighSurrogate(ch)) { 1075 if (j == searchLast) { 1076 // missing low surrogate, fine, like String.indexOf(String) 1077 return true; 1078 } 1079 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1080 return true; 1081 } 1082 } else { 1083 // ch is in the Basic Multilingual Plane 1084 return true; 1085 } 1086 } 1087 } 1088 } 1089 return false; 1090 } 1091 1092 /** 1093 * <p> 1094 * Checks if the CharSequence contains any character in the given set of characters. 1095 * </p> 1096 * 1097 * <p> 1098 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return 1099 * {@code false}. 1100 * </p> 1101 * 1102 * <pre> 1103 * StringUtils.containsAny(null, *) = false 1104 * StringUtils.containsAny("", *) = false 1105 * StringUtils.containsAny(*, null) = false 1106 * StringUtils.containsAny(*, "") = false 1107 * StringUtils.containsAny("zzabyycdxx", "za") = true 1108 * StringUtils.containsAny("zzabyycdxx", "by") = true 1109 * StringUtils.containsAny("zzabyycdxx", "zy") = true 1110 * StringUtils.containsAny("zzabyycdxx", "\tx") = true 1111 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true 1112 * StringUtils.containsAny("aba", "z") = false 1113 * </pre> 1114 * 1115 * @param cs 1116 * the CharSequence to check, may be null 1117 * @param searchChars 1118 * the chars to search for, may be null 1119 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input 1120 * @since 2.4 1121 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1122 */ 1123 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1124 if (searchChars == null) { 1125 return false; 1126 } 1127 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1128 } 1129 1130 /** 1131 * <p>Checks if the CharSequence contains any of the CharSequences in the given array.</p> 1132 * 1133 * <p> 1134 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero 1135 * length search array will return {@code false}. 1136 * </p> 1137 * 1138 * <pre> 1139 * StringUtils.containsAny(null, *) = false 1140 * StringUtils.containsAny("", *) = false 1141 * StringUtils.containsAny(*, null) = false 1142 * StringUtils.containsAny(*, []) = false 1143 * StringUtils.containsAny("abcd", "ab", null) = true 1144 * StringUtils.containsAny("abcd", "ab", "cd") = true 1145 * StringUtils.containsAny("abc", "d", "abc") = true 1146 * </pre> 1147 * 1148 * 1149 * @param cs The CharSequence to check, may be null 1150 * @param searchCharSequences The array of CharSequences to search for, may be null. 1151 * Individual CharSequences may be null as well. 1152 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1153 * @since 3.4 1154 */ 1155 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) { 1156 if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) { 1157 return false; 1158 } 1159 for (final CharSequence searchCharSequence : searchCharSequences) { 1160 if (contains(cs, searchCharSequence)) { 1161 return true; 1162 } 1163 } 1164 return false; 1165 } 1166 1167 /** 1168 * <p>Checks if CharSequence contains a search CharSequence irrespective of case, 1169 * handling {@code null}. Case-insensitivity is defined as by 1170 * {@link String#equalsIgnoreCase(String)}. 1171 * 1172 * <p>A {@code null} CharSequence will return {@code false}.</p> 1173 * 1174 * <pre> 1175 * StringUtils.containsIgnoreCase(null, *) = false 1176 * StringUtils.containsIgnoreCase(*, null) = false 1177 * StringUtils.containsIgnoreCase("", "") = true 1178 * StringUtils.containsIgnoreCase("abc", "") = true 1179 * StringUtils.containsIgnoreCase("abc", "a") = true 1180 * StringUtils.containsIgnoreCase("abc", "z") = false 1181 * StringUtils.containsIgnoreCase("abc", "A") = true 1182 * StringUtils.containsIgnoreCase("abc", "Z") = false 1183 * </pre> 1184 * 1185 * @param str the CharSequence to check, may be null 1186 * @param searchStr the CharSequence to find, may be null 1187 * @return true if the CharSequence contains the search CharSequence irrespective of 1188 * case or false if not or {@code null} string input 1189 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence) 1190 */ 1191 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1192 if (str == null || searchStr == null) { 1193 return false; 1194 } 1195 final int len = searchStr.length(); 1196 final int max = str.length() - len; 1197 for (int i = 0; i <= max; i++) { 1198 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) { 1199 return true; 1200 } 1201 } 1202 return false; 1203 } 1204 1205 // ContainsNone 1206 //----------------------------------------------------------------------- 1207 /** 1208 * <p>Checks that the CharSequence does not contain certain characters.</p> 1209 * 1210 * <p>A {@code null} CharSequence will return {@code true}. 1211 * A {@code null} invalid character array will return {@code true}. 1212 * An empty CharSequence (length()=0) always returns true.</p> 1213 * 1214 * <pre> 1215 * StringUtils.containsNone(null, *) = true 1216 * StringUtils.containsNone(*, null) = true 1217 * StringUtils.containsNone("", *) = true 1218 * StringUtils.containsNone("ab", '') = true 1219 * StringUtils.containsNone("abab", 'xyz') = true 1220 * StringUtils.containsNone("ab1", 'xyz') = true 1221 * StringUtils.containsNone("abz", 'xyz') = false 1222 * </pre> 1223 * 1224 * @param cs the CharSequence to check, may be null 1225 * @param searchChars an array of invalid chars, may be null 1226 * @return true if it contains none of the invalid chars, or is null 1227 * @since 2.0 1228 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1229 */ 1230 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1231 if (cs == null || searchChars == null) { 1232 return true; 1233 } 1234 final int csLen = cs.length(); 1235 final int csLast = csLen - 1; 1236 final int searchLen = searchChars.length; 1237 final int searchLast = searchLen - 1; 1238 for (int i = 0; i < csLen; i++) { 1239 final char ch = cs.charAt(i); 1240 for (int j = 0; j < searchLen; j++) { 1241 if (searchChars[j] == ch) { 1242 if (Character.isHighSurrogate(ch)) { 1243 if (j == searchLast) { 1244 // missing low surrogate, fine, like String.indexOf(String) 1245 return false; 1246 } 1247 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1248 return false; 1249 } 1250 } else { 1251 // ch is in the Basic Multilingual Plane 1252 return false; 1253 } 1254 } 1255 } 1256 } 1257 return true; 1258 } 1259 1260 /** 1261 * <p>Checks that the CharSequence does not contain certain characters.</p> 1262 * 1263 * <p>A {@code null} CharSequence will return {@code true}. 1264 * A {@code null} invalid character array will return {@code true}. 1265 * An empty String ("") always returns true.</p> 1266 * 1267 * <pre> 1268 * StringUtils.containsNone(null, *) = true 1269 * StringUtils.containsNone(*, null) = true 1270 * StringUtils.containsNone("", *) = true 1271 * StringUtils.containsNone("ab", "") = true 1272 * StringUtils.containsNone("abab", "xyz") = true 1273 * StringUtils.containsNone("ab1", "xyz") = true 1274 * StringUtils.containsNone("abz", "xyz") = false 1275 * </pre> 1276 * 1277 * @param cs the CharSequence to check, may be null 1278 * @param invalidChars a String of invalid chars, may be null 1279 * @return true if it contains none of the invalid chars, or is null 1280 * @since 2.0 1281 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1282 */ 1283 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1284 if (cs == null || invalidChars == null) { 1285 return true; 1286 } 1287 return containsNone(cs, invalidChars.toCharArray()); 1288 } 1289 1290 // ContainsOnly 1291 //----------------------------------------------------------------------- 1292 /** 1293 * <p>Checks if the CharSequence contains only certain characters.</p> 1294 * 1295 * <p>A {@code null} CharSequence will return {@code false}. 1296 * A {@code null} valid character array will return {@code false}. 1297 * An empty CharSequence (length()=0) always returns {@code true}.</p> 1298 * 1299 * <pre> 1300 * StringUtils.containsOnly(null, *) = false 1301 * StringUtils.containsOnly(*, null) = false 1302 * StringUtils.containsOnly("", *) = true 1303 * StringUtils.containsOnly("ab", '') = false 1304 * StringUtils.containsOnly("abab", 'abc') = true 1305 * StringUtils.containsOnly("ab1", 'abc') = false 1306 * StringUtils.containsOnly("abz", 'abc') = false 1307 * </pre> 1308 * 1309 * @param cs the String to check, may be null 1310 * @param valid an array of valid chars, may be null 1311 * @return true if it only contains valid chars and is non-null 1312 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1313 */ 1314 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1315 // All these pre-checks are to maintain API with an older version 1316 if (valid == null || cs == null) { 1317 return false; 1318 } 1319 if (cs.length() == 0) { 1320 return true; 1321 } 1322 if (valid.length == 0) { 1323 return false; 1324 } 1325 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1326 } 1327 1328 /** 1329 * <p>Checks if the CharSequence contains only certain characters.</p> 1330 * 1331 * <p>A {@code null} CharSequence will return {@code false}. 1332 * A {@code null} valid character String will return {@code false}. 1333 * An empty String (length()=0) always returns {@code true}.</p> 1334 * 1335 * <pre> 1336 * StringUtils.containsOnly(null, *) = false 1337 * StringUtils.containsOnly(*, null) = false 1338 * StringUtils.containsOnly("", *) = true 1339 * StringUtils.containsOnly("ab", "") = false 1340 * StringUtils.containsOnly("abab", "abc") = true 1341 * StringUtils.containsOnly("ab1", "abc") = false 1342 * StringUtils.containsOnly("abz", "abc") = false 1343 * </pre> 1344 * 1345 * @param cs the CharSequence to check, may be null 1346 * @param validChars a String of valid chars, may be null 1347 * @return true if it only contains valid chars and is non-null 1348 * @since 2.0 1349 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1350 */ 1351 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1352 if (cs == null || validChars == null) { 1353 return false; 1354 } 1355 return containsOnly(cs, validChars.toCharArray()); 1356 } 1357 1358 /** 1359 * <p>Check whether the given CharSequence contains any whitespace characters.</p> 1360 * 1361 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1362 * 1363 * @param seq the CharSequence to check (may be {@code null}) 1364 * @return {@code true} if the CharSequence is not empty and 1365 * contains at least 1 (breaking) whitespace character 1366 * @since 3.0 1367 */ 1368 // From org.springframework.util.StringUtils, under Apache License 2.0 1369 public static boolean containsWhitespace(final CharSequence seq) { 1370 if (isEmpty(seq)) { 1371 return false; 1372 } 1373 final int strLen = seq.length(); 1374 for (int i = 0; i < strLen; i++) { 1375 if (Character.isWhitespace(seq.charAt(i))) { 1376 return true; 1377 } 1378 } 1379 return false; 1380 } 1381 1382 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) { 1383 for (int i = 0; i < decomposed.length(); i++) { 1384 if (decomposed.charAt(i) == '\u0141') { 1385 decomposed.deleteCharAt(i); 1386 decomposed.insert(i, 'L'); 1387 } else if (decomposed.charAt(i) == '\u0142') { 1388 decomposed.deleteCharAt(i); 1389 decomposed.insert(i, 'l'); 1390 } 1391 } 1392 } 1393 1394 /** 1395 * <p>Counts how many times the char appears in the given string.</p> 1396 * 1397 * <p>A {@code null} or empty ("") String input returns {@code 0}.</p> 1398 * 1399 * <pre> 1400 * StringUtils.countMatches(null, *) = 0 1401 * StringUtils.countMatches("", *) = 0 1402 * StringUtils.countMatches("abba", 0) = 0 1403 * StringUtils.countMatches("abba", 'a') = 2 1404 * StringUtils.countMatches("abba", 'b') = 2 1405 * StringUtils.countMatches("abba", 'x') = 0 1406 * </pre> 1407 * 1408 * @param str the CharSequence to check, may be null 1409 * @param ch the char to count 1410 * @return the number of occurrences, 0 if the CharSequence is {@code null} 1411 * @since 3.4 1412 */ 1413 public static int countMatches(final CharSequence str, final char ch) { 1414 if (isEmpty(str)) { 1415 return 0; 1416 } 1417 int count = 0; 1418 // We could also call str.toCharArray() for faster look ups but that would generate more garbage. 1419 for (int i = 0; i < str.length(); i++) { 1420 if (ch == str.charAt(i)) { 1421 count++; 1422 } 1423 } 1424 return count; 1425 } 1426 1427 // Count matches 1428 //----------------------------------------------------------------------- 1429 /** 1430 * <p>Counts how many times the substring appears in the larger string.</p> 1431 * 1432 * <p>A {@code null} or empty ("") String input returns {@code 0}.</p> 1433 * 1434 * <pre> 1435 * StringUtils.countMatches(null, *) = 0 1436 * StringUtils.countMatches("", *) = 0 1437 * StringUtils.countMatches("abba", null) = 0 1438 * StringUtils.countMatches("abba", "") = 0 1439 * StringUtils.countMatches("abba", "a") = 2 1440 * StringUtils.countMatches("abba", "ab") = 1 1441 * StringUtils.countMatches("abba", "xxx") = 0 1442 * </pre> 1443 * 1444 * @param str the CharSequence to check, may be null 1445 * @param sub the substring to count, may be null 1446 * @return the number of occurrences, 0 if either CharSequence is {@code null} 1447 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 1448 */ 1449 public static int countMatches(final CharSequence str, final CharSequence sub) { 1450 if (isEmpty(str) || isEmpty(sub)) { 1451 return 0; 1452 } 1453 int count = 0; 1454 int idx = 0; 1455 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 1456 count++; 1457 idx += sub.length(); 1458 } 1459 return count; 1460 } 1461 1462 /** 1463 * <p>Returns either the passed in CharSequence, or if the CharSequence is 1464 * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.</p> 1465 * 1466 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1467 * 1468 * <pre> 1469 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 1470 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 1471 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 1472 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 1473 * StringUtils.defaultIfBlank("", null) = null 1474 * </pre> 1475 * @param <T> the specific kind of CharSequence 1476 * @param str the CharSequence to check, may be null 1477 * @param defaultStr the default CharSequence to return 1478 * if the input is whitespace, empty ("") or {@code null}, may be null 1479 * @return the passed in CharSequence, or the default 1480 * @see StringUtils#defaultString(String, String) 1481 */ 1482 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 1483 return isBlank(str) ? defaultStr : str; 1484 } 1485 1486 /** 1487 * <p>Returns either the passed in CharSequence, or if the CharSequence is 1488 * empty or {@code null}, the value of {@code defaultStr}.</p> 1489 * 1490 * <pre> 1491 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 1492 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 1493 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 1494 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 1495 * StringUtils.defaultIfEmpty("", null) = null 1496 * </pre> 1497 * @param <T> the specific kind of CharSequence 1498 * @param str the CharSequence to check, may be null 1499 * @param defaultStr the default CharSequence to return 1500 * if the input is empty ("") or {@code null}, may be null 1501 * @return the passed in CharSequence, or the default 1502 * @see StringUtils#defaultString(String, String) 1503 */ 1504 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 1505 return isEmpty(str) ? defaultStr : str; 1506 } 1507 1508 /** 1509 * <p>Returns either the passed in String, 1510 * or if the String is {@code null}, an empty String ("").</p> 1511 * 1512 * <pre> 1513 * StringUtils.defaultString(null) = "" 1514 * StringUtils.defaultString("") = "" 1515 * StringUtils.defaultString("bat") = "bat" 1516 * </pre> 1517 * 1518 * @see ObjectUtils#toString(Object) 1519 * @see String#valueOf(Object) 1520 * @param str the String to check, may be null 1521 * @return the passed in String, or the empty String if it 1522 * was {@code null} 1523 */ 1524 public static String defaultString(final String str) { 1525 return defaultString(str, EMPTY); 1526 } 1527 1528 /** 1529 * <p>Returns either the passed in String, or if the String is 1530 * {@code null}, the value of {@code defaultStr}.</p> 1531 * 1532 * <pre> 1533 * StringUtils.defaultString(null, "NULL") = "NULL" 1534 * StringUtils.defaultString("", "NULL") = "" 1535 * StringUtils.defaultString("bat", "NULL") = "bat" 1536 * </pre> 1537 * 1538 * @see ObjectUtils#toString(Object,String) 1539 * @see String#valueOf(Object) 1540 * @param str the String to check, may be null 1541 * @param defaultStr the default String to return 1542 * if the input is {@code null}, may be null 1543 * @return the passed in String, or the default if it was {@code null} 1544 */ 1545 public static String defaultString(final String str, final String defaultStr) { 1546 return str == null ? defaultStr : str; 1547 } 1548 1549 // Delete 1550 //----------------------------------------------------------------------- 1551 /** 1552 * <p>Deletes all whitespaces from a String as defined by 1553 * {@link Character#isWhitespace(char)}.</p> 1554 * 1555 * <pre> 1556 * StringUtils.deleteWhitespace(null) = null 1557 * StringUtils.deleteWhitespace("") = "" 1558 * StringUtils.deleteWhitespace("abc") = "abc" 1559 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1560 * </pre> 1561 * 1562 * @param str the String to delete whitespace from, may be null 1563 * @return the String without whitespaces, {@code null} if null String input 1564 */ 1565 public static String deleteWhitespace(final String str) { 1566 if (isEmpty(str)) { 1567 return str; 1568 } 1569 final int sz = str.length(); 1570 final char[] chs = new char[sz]; 1571 int count = 0; 1572 for (int i = 0; i < sz; i++) { 1573 if (!Character.isWhitespace(str.charAt(i))) { 1574 chs[count++] = str.charAt(i); 1575 } 1576 } 1577 if (count == sz) { 1578 return str; 1579 } 1580 return new String(chs, 0, count); 1581 } 1582 1583 // Difference 1584 //----------------------------------------------------------------------- 1585 /** 1586 * <p>Compares two Strings, and returns the portion where they differ. 1587 * More precisely, return the remainder of the second String, 1588 * starting from where it's different from the first. This means that 1589 * the difference between "abc" and "ab" is the empty String and not "c". </p> 1590 * 1591 * <p>For example, 1592 * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p> 1593 * 1594 * <pre> 1595 * StringUtils.difference(null, null) = null 1596 * StringUtils.difference("", "") = "" 1597 * StringUtils.difference("", "abc") = "abc" 1598 * StringUtils.difference("abc", "") = "" 1599 * StringUtils.difference("abc", "abc") = "" 1600 * StringUtils.difference("abc", "ab") = "" 1601 * StringUtils.difference("ab", "abxyz") = "xyz" 1602 * StringUtils.difference("abcde", "abxyz") = "xyz" 1603 * StringUtils.difference("abcde", "xyz") = "xyz" 1604 * </pre> 1605 * 1606 * @param str1 the first String, may be null 1607 * @param str2 the second String, may be null 1608 * @return the portion of str2 where it differs from str1; returns the 1609 * empty String if they are equal 1610 * @see #indexOfDifference(CharSequence,CharSequence) 1611 * @since 2.0 1612 */ 1613 public static String difference(final String str1, final String str2) { 1614 if (str1 == null) { 1615 return str2; 1616 } 1617 if (str2 == null) { 1618 return str1; 1619 } 1620 final int at = indexOfDifference(str1, str2); 1621 if (at == INDEX_NOT_FOUND) { 1622 return EMPTY; 1623 } 1624 return str2.substring(at); 1625 } 1626 1627 /** 1628 * <p>Check if a CharSequence ends with a specified suffix.</p> 1629 * 1630 * <p>{@code null}s are handled without exceptions. Two {@code null} 1631 * references are considered to be equal. The comparison is case sensitive.</p> 1632 * 1633 * <pre> 1634 * StringUtils.endsWith(null, null) = true 1635 * StringUtils.endsWith(null, "def") = false 1636 * StringUtils.endsWith("abcdef", null) = false 1637 * StringUtils.endsWith("abcdef", "def") = true 1638 * StringUtils.endsWith("ABCDEF", "def") = false 1639 * StringUtils.endsWith("ABCDEF", "cde") = false 1640 * StringUtils.endsWith("ABCDEF", "") = true 1641 * </pre> 1642 * 1643 * @see java.lang.String#endsWith(String) 1644 * @param str the CharSequence to check, may be null 1645 * @param suffix the suffix to find, may be null 1646 * @return {@code true} if the CharSequence ends with the suffix, case sensitive, or 1647 * both {@code null} 1648 * @since 2.4 1649 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1650 */ 1651 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1652 return endsWith(str, suffix, false); 1653 } 1654 1655 /** 1656 * <p>Check if a CharSequence ends with a specified suffix (optionally case insensitive).</p> 1657 * 1658 * @see java.lang.String#endsWith(String) 1659 * @param str the CharSequence to check, may be null 1660 * @param suffix the suffix to find, may be null 1661 * @param ignoreCase indicates whether the compare should ignore case 1662 * (case insensitive) or not. 1663 * @return {@code true} if the CharSequence starts with the prefix or 1664 * both {@code null} 1665 */ 1666 private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) { 1667 if (str == null || suffix == null) { 1668 return str == suffix; 1669 } 1670 if (suffix.length() > str.length()) { 1671 return false; 1672 } 1673 final int strOffset = str.length() - suffix.length(); 1674 return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length()); 1675 } 1676 1677 /** 1678 * <p>Check if a CharSequence ends with any of the provided case-sensitive suffixes.</p> 1679 * 1680 * <pre> 1681 * StringUtils.endsWithAny(null, null) = false 1682 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1683 * StringUtils.endsWithAny("abcxyz", null) = false 1684 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1685 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1686 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1687 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1688 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1689 * </pre> 1690 * 1691 * @param sequence the CharSequence to check, may be null 1692 * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null} 1693 * @see StringUtils#endsWith(CharSequence, CharSequence) 1694 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or 1695 * the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}. 1696 * @since 3.0 1697 */ 1698 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1699 if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { 1700 return false; 1701 } 1702 for (final CharSequence searchString : searchStrings) { 1703 if (endsWith(sequence, searchString)) { 1704 return true; 1705 } 1706 } 1707 return false; 1708 } 1709 1710 /** 1711 * <p>Case insensitive check if a CharSequence ends with a specified suffix.</p> 1712 * 1713 * <p>{@code null}s are handled without exceptions. Two {@code null} 1714 * references are considered to be equal. The comparison is case insensitive.</p> 1715 * 1716 * <pre> 1717 * StringUtils.endsWithIgnoreCase(null, null) = true 1718 * StringUtils.endsWithIgnoreCase(null, "def") = false 1719 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1720 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1721 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1722 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1723 * </pre> 1724 * 1725 * @see java.lang.String#endsWith(String) 1726 * @param str the CharSequence to check, may be null 1727 * @param suffix the suffix to find, may be null 1728 * @return {@code true} if the CharSequence ends with the suffix, case insensitive, or 1729 * both {@code null} 1730 * @since 2.4 1731 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1732 */ 1733 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1734 return endsWith(str, suffix, true); 1735 } 1736 1737 // Equals 1738 //----------------------------------------------------------------------- 1739 /** 1740 * <p>Compares two CharSequences, returning {@code true} if they represent 1741 * equal sequences of characters.</p> 1742 * 1743 * <p>{@code null}s are handled without exceptions. Two {@code null} 1744 * references are considered to be equal. The comparison is <strong>case sensitive</strong>.</p> 1745 * 1746 * <pre> 1747 * StringUtils.equals(null, null) = true 1748 * StringUtils.equals(null, "abc") = false 1749 * StringUtils.equals("abc", null) = false 1750 * StringUtils.equals("abc", "abc") = true 1751 * StringUtils.equals("abc", "ABC") = false 1752 * </pre> 1753 * 1754 * @param cs1 the first CharSequence, may be {@code null} 1755 * @param cs2 the second CharSequence, may be {@code null} 1756 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} 1757 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1758 * @see Object#equals(Object) 1759 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1760 */ 1761 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1762 if (cs1 == cs2) { 1763 return true; 1764 } 1765 if (cs1 == null || cs2 == null) { 1766 return false; 1767 } 1768 if (cs1.length() != cs2.length()) { 1769 return false; 1770 } 1771 if (cs1 instanceof String && cs2 instanceof String) { 1772 return cs1.equals(cs2); 1773 } 1774 // Step-wise comparison 1775 final int length = cs1.length(); 1776 for (int i = 0; i < length; i++) { 1777 if (cs1.charAt(i) != cs2.charAt(i)) { 1778 return false; 1779 } 1780 } 1781 return true; 1782 } 1783 1784 /** 1785 * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1786 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}.</p> 1787 * 1788 * <pre> 1789 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1790 * StringUtils.equalsAny(null, null, null) = true 1791 * StringUtils.equalsAny(null, "abc", "def") = false 1792 * StringUtils.equalsAny("abc", null, "def") = false 1793 * StringUtils.equalsAny("abc", "abc", "def") = true 1794 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1795 * </pre> 1796 * 1797 * @param string to compare, may be {@code null}. 1798 * @param searchStrings a vararg of strings, may be {@code null}. 1799 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; 1800 * {@code false} if {@code searchStrings} is null or contains no matches. 1801 * @since 3.5 1802 */ 1803 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1804 if (ArrayUtils.isNotEmpty(searchStrings)) { 1805 for (final CharSequence next : searchStrings) { 1806 if (equals(string, next)) { 1807 return true; 1808 } 1809 } 1810 } 1811 return false; 1812 } 1813 1814 /** 1815 * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1816 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.</p> 1817 * 1818 * <pre> 1819 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1820 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1821 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1822 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1823 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1824 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 1825 * </pre> 1826 * 1827 * @param string to compare, may be {@code null}. 1828 * @param searchStrings a vararg of strings, may be {@code null}. 1829 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings}; 1830 * {@code false} if {@code searchStrings} is null or contains no matches. 1831 * @since 3.5 1832 */ 1833 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) { 1834 if (ArrayUtils.isNotEmpty(searchStrings)) { 1835 for (final CharSequence next : searchStrings) { 1836 if (equalsIgnoreCase(string, next)) { 1837 return true; 1838 } 1839 } 1840 } 1841 return false; 1842 } 1843 1844 /** 1845 * <p>Compares two CharSequences, returning {@code true} if they represent 1846 * equal sequences of characters, ignoring case.</p> 1847 * 1848 * <p>{@code null}s are handled without exceptions. Two {@code null} 1849 * references are considered equal. The comparison is <strong>case insensitive</strong>.</p> 1850 * 1851 * <pre> 1852 * StringUtils.equalsIgnoreCase(null, null) = true 1853 * StringUtils.equalsIgnoreCase(null, "abc") = false 1854 * StringUtils.equalsIgnoreCase("abc", null) = false 1855 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1856 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1857 * </pre> 1858 * 1859 * @param cs1 the first CharSequence, may be {@code null} 1860 * @param cs2 the second CharSequence, may be {@code null} 1861 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null} 1862 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1863 * @see #equals(CharSequence, CharSequence) 1864 */ 1865 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1866 if (cs1 == cs2) { 1867 return true; 1868 } 1869 if (cs1 == null || cs2 == null) { 1870 return false; 1871 } 1872 if (cs1.length() != cs2.length()) { 1873 return false; 1874 } 1875 return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length()); 1876 } 1877 1878 /** 1879 * <p>Returns the first value in the array which is not empty (""), 1880 * {@code null} or whitespace only.</p> 1881 * 1882 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1883 * 1884 * <p>If all values are blank or the array is {@code null} 1885 * or empty then {@code null} is returned.</p> 1886 * 1887 * <pre> 1888 * StringUtils.firstNonBlank(null, null, null) = null 1889 * StringUtils.firstNonBlank(null, "", " ") = null 1890 * StringUtils.firstNonBlank("abc") = "abc" 1891 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1892 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1893 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1894 * StringUtils.firstNonBlank() = null 1895 * </pre> 1896 * 1897 * @param <T> the specific kind of CharSequence 1898 * @param values the values to test, may be {@code null} or empty 1899 * @return the first value from {@code values} which is not blank, 1900 * or {@code null} if there are no non-blank values 1901 * @since 3.8 1902 */ 1903 @SafeVarargs 1904 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1905 if (values != null) { 1906 for (final T val : values) { 1907 if (isNotBlank(val)) { 1908 return val; 1909 } 1910 } 1911 } 1912 return null; 1913 } 1914 1915 /** 1916 * <p>Returns the first value in the array which is not empty.</p> 1917 * 1918 * <p>If all values are empty or the array is {@code null} 1919 * or empty then {@code null} is returned.</p> 1920 * 1921 * <pre> 1922 * StringUtils.firstNonEmpty(null, null, null) = null 1923 * StringUtils.firstNonEmpty(null, null, "") = null 1924 * StringUtils.firstNonEmpty(null, "", " ") = " " 1925 * StringUtils.firstNonEmpty("abc") = "abc" 1926 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1927 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1928 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1929 * StringUtils.firstNonEmpty() = null 1930 * </pre> 1931 * 1932 * @param <T> the specific kind of CharSequence 1933 * @param values the values to test, may be {@code null} or empty 1934 * @return the first value from {@code values} which is not empty, 1935 * or {@code null} if there are no non-empty values 1936 * @since 3.8 1937 */ 1938 @SafeVarargs 1939 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 1940 if (values != null) { 1941 for (final T val : values) { 1942 if (isNotEmpty(val)) { 1943 return val; 1944 } 1945 } 1946 } 1947 return null; 1948 } 1949 1950 /** 1951 * Calls {@link String#getBytes(Charset)} in a null-safe manner. 1952 * 1953 * @param string input string 1954 * @param charset The {@link Charset} to encode the {@code String}. If null, then use the default Charset. 1955 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 1956 * @see String#getBytes(Charset) 1957 * @since 3.10 1958 */ 1959 public static byte[] getBytes(final String string, final Charset charset) { 1960 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 1961 } 1962 1963 /** 1964 * Calls {@link String#getBytes(String)} in a null-safe manner. 1965 * 1966 * @param string input string 1967 * @param charset The {@link Charset} name to encode the {@code String}. If null, then use the default Charset. 1968 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 1969 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 1970 * @see String#getBytes(String) 1971 * @since 3.10 1972 */ 1973 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 1974 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 1975 } 1976 1977 /** 1978 * <p>Compares all Strings in an array and returns the initial sequence of 1979 * characters that is common to all of them.</p> 1980 * 1981 * <p>For example, 1982 * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "}</p> 1983 * 1984 * <pre> 1985 * StringUtils.getCommonPrefix(null) = "" 1986 * StringUtils.getCommonPrefix(new String[] {}) = "" 1987 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 1988 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 1989 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 1990 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 1991 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 1992 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 1993 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 1994 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 1995 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 1996 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 1997 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 1998 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 1999 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 2000 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 2001 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 2002 * </pre> 2003 * 2004 * @param strs array of String objects, entries may be null 2005 * @return the initial sequence of characters that are common to all Strings 2006 * in the array; empty String if the array is null, the elements are all null 2007 * or if there is no common prefix. 2008 * @since 2.4 2009 */ 2010 public static String getCommonPrefix(final String... strs) { 2011 if (ArrayUtils.isEmpty(strs)) { 2012 return EMPTY; 2013 } 2014 final int smallestIndexOfDiff = indexOfDifference(strs); 2015 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2016 // all strings were identical 2017 if (strs[0] == null) { 2018 return EMPTY; 2019 } 2020 return strs[0]; 2021 } else if (smallestIndexOfDiff == 0) { 2022 // there were no common initial characters 2023 return EMPTY; 2024 } else { 2025 // we found a common initial character sequence 2026 return strs[0].substring(0, smallestIndexOfDiff); 2027 } 2028 } 2029 2030 /** 2031 * <p>Checks if a String {@code str} contains Unicode digits, 2032 * if yes then concatenate all the digits in {@code str} and return it as a String.</p> 2033 * 2034 * <p>An empty ("") String will be returned if no digits found in {@code str}.</p> 2035 * 2036 * <pre> 2037 * StringUtils.getDigits(null) = null 2038 * StringUtils.getDigits("") = "" 2039 * StringUtils.getDigits("abc") = "" 2040 * StringUtils.getDigits("1000$") = "1000" 2041 * StringUtils.getDigits("1123~45") = "112345" 2042 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2043 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2044 * </pre> 2045 * 2046 * @param str the String to extract digits from, may be null 2047 * @return String with only digits, 2048 * or an empty ("") String if no digits found, 2049 * or {@code null} String if {@code str} is null 2050 * @since 3.6 2051 */ 2052 public static String getDigits(final String str) { 2053 if (isEmpty(str)) { 2054 return str; 2055 } 2056 final int sz = str.length(); 2057 final StringBuilder strDigits = new StringBuilder(sz); 2058 for (int i = 0; i < sz; i++) { 2059 final char tempChar = str.charAt(i); 2060 if (Character.isDigit(tempChar)) { 2061 strDigits.append(tempChar); 2062 } 2063 } 2064 return strDigits.toString(); 2065 } 2066 2067 /** 2068 * <p>Find the Fuzzy Distance which indicates the similarity score between two Strings.</p> 2069 * 2070 * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text, 2071 * TextMate, Atom and others. One point is given for every matched character. Subsequent 2072 * matches yield two bonus points. A higher score indicates a higher similarity.</p> 2073 * 2074 * <pre> 2075 * StringUtils.getFuzzyDistance(null, null, null) = IllegalArgumentException 2076 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2077 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2078 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2079 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2080 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2081 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2082 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2083 * </pre> 2084 * 2085 * @param term a full term that should be matched against, must not be null 2086 * @param query the query that will be matched against a term, must not be null 2087 * @param locale This string matching logic is case insensitive. A locale is necessary to normalize 2088 * both Strings to lower case. 2089 * @return result score 2090 * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null} 2091 * @since 3.4 2092 * @deprecated as of 3.6, use commons-text 2093 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2094 * FuzzyScore</a> instead 2095 */ 2096 @Deprecated 2097 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2098 if (term == null || query == null) { 2099 throw new IllegalArgumentException("Strings must not be null"); 2100 } else if (locale == null) { 2101 throw new IllegalArgumentException("Locale must not be null"); 2102 } 2103 2104 // fuzzy logic is case insensitive. We normalize the Strings to lower 2105 // case right from the start. Turning characters to lower case 2106 // via Character.toLowerCase(char) is unfortunately insufficient 2107 // as it does not accept a locale. 2108 final String termLowerCase = term.toString().toLowerCase(locale); 2109 final String queryLowerCase = query.toString().toLowerCase(locale); 2110 2111 // the resulting score 2112 int score = 0; 2113 2114 // the position in the term which will be scanned next for potential 2115 // query character matches 2116 int termIndex = 0; 2117 2118 // index of the previously matched character in the term 2119 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2120 2121 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2122 final char queryChar = queryLowerCase.charAt(queryIndex); 2123 2124 boolean termCharacterMatchFound = false; 2125 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2126 final char termChar = termLowerCase.charAt(termIndex); 2127 2128 if (queryChar == termChar) { 2129 // simple character matches result in one point 2130 score++; 2131 2132 // subsequent character matches further improve 2133 // the score. 2134 if (previousMatchingCharacterIndex + 1 == termIndex) { 2135 score += 2; 2136 } 2137 2138 previousMatchingCharacterIndex = termIndex; 2139 2140 // we can leave the nested loop. Every character in the 2141 // query can match at most one character in the term. 2142 termCharacterMatchFound = true; 2143 } 2144 } 2145 } 2146 2147 return score; 2148 } 2149 2150 /** 2151 * <p>Returns either the passed in CharSequence, or if the CharSequence is 2152 * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}.</p> 2153 * 2154 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 2155 * 2156 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2157 * 2158 * <pre> 2159 * {@code 2160 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2161 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2162 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2163 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2164 * StringUtils.getIfBlank("", () -> null) = null 2165 * StringUtils.getIfBlank("", null) = null 2166 * }</pre> 2167 * @param <T> the specific kind of CharSequence 2168 * @param str the CharSequence to check, may be null 2169 * @param defaultSupplier the supplier of default CharSequence to return 2170 * if the input is whitespace, empty ("") or {@code null}, may be null 2171 * @return the passed in CharSequence, or the default 2172 * @see StringUtils#defaultString(String, String) 2173 * @since 3.10 2174 */ 2175 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2176 return isBlank(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str; 2177 } 2178 2179 /** 2180 * <p>Returns either the passed in CharSequence, or if the CharSequence is 2181 * empty or {@code null}, the value supplied by {@code defaultStrSupplier}.</p> 2182 * 2183 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2184 * 2185 * <pre> 2186 * {@code 2187 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2188 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2189 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2190 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2191 * StringUtils.getIfEmpty("", () -> null) = null 2192 * StringUtils.getIfEmpty("", null) = null 2193 * } 2194 * </pre> 2195 * @param <T> the specific kind of CharSequence 2196 * @param str the CharSequence to check, may be null 2197 * @param defaultSupplier the supplier of default CharSequence to return 2198 * if the input is empty ("") or {@code null}, may be null 2199 * @return the passed in CharSequence, or the default 2200 * @see StringUtils#defaultString(String, String) 2201 * @since 3.10 2202 */ 2203 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2204 return isEmpty(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str; 2205 } 2206 2207 /** 2208 * <p>Find the Jaro Winkler Distance which indicates the similarity score between two Strings.</p> 2209 * 2210 * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. 2211 * Winkler increased this measure for matching initial characters.</p> 2212 * 2213 * <p>This implementation is based on the Jaro Winkler similarity algorithm 2214 * from <a href="http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.</p> 2215 * 2216 * <pre> 2217 * StringUtils.getJaroWinklerDistance(null, null) = IllegalArgumentException 2218 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2219 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2220 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2221 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2222 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2223 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2224 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2225 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2226 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2227 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2228 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2229 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2230 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2231 * </pre> 2232 * 2233 * @param first the first String, must not be null 2234 * @param second the second String, must not be null 2235 * @return result distance 2236 * @throws IllegalArgumentException if either String input {@code null} 2237 * @since 3.3 2238 * @deprecated as of 3.6, use commons-text 2239 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2240 * JaroWinklerDistance</a> instead 2241 */ 2242 @Deprecated 2243 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2244 final double DEFAULT_SCALING_FACTOR = 0.1; 2245 2246 if (first == null || second == null) { 2247 throw new IllegalArgumentException("Strings must not be null"); 2248 } 2249 2250 final int[] mtp = matches(first, second); 2251 final double m = mtp[0]; 2252 if (m == 0) { 2253 return 0D; 2254 } 2255 final double j = ((m / first.length() + m / second.length() + (m - mtp[1]) / m)) / 3; 2256 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2257 return Math.round(jw * 100.0D) / 100.0D; 2258 } 2259 2260 // Misc 2261 //----------------------------------------------------------------------- 2262 /** 2263 * <p>Find the Levenshtein distance between two Strings.</p> 2264 * 2265 * <p>This is the number of changes needed to change one String into 2266 * another, where each change is a single character modification (deletion, 2267 * insertion or substitution).</p> 2268 * 2269 * <p>The implementation uses a single-dimensional array of length s.length() + 1. See 2270 * <a href="http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2271 * http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p> 2272 * 2273 * <pre> 2274 * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException 2275 * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException 2276 * StringUtils.getLevenshteinDistance("", "") = 0 2277 * StringUtils.getLevenshteinDistance("", "a") = 1 2278 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2279 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2280 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2281 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2282 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2283 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2284 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2285 * </pre> 2286 * 2287 * @param s the first String, must not be null 2288 * @param t the second String, must not be null 2289 * @return result distance 2290 * @throws IllegalArgumentException if either String input {@code null} 2291 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to 2292 * getLevenshteinDistance(CharSequence, CharSequence) 2293 * @deprecated as of 3.6, use commons-text 2294 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2295 * LevenshteinDistance</a> instead 2296 */ 2297 @Deprecated 2298 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2299 if (s == null || t == null) { 2300 throw new IllegalArgumentException("Strings must not be null"); 2301 } 2302 2303 int n = s.length(); 2304 int m = t.length(); 2305 2306 if (n == 0) { 2307 return m; 2308 } else if (m == 0) { 2309 return n; 2310 } 2311 2312 if (n > m) { 2313 // swap the input strings to consume less memory 2314 final CharSequence tmp = s; 2315 s = t; 2316 t = tmp; 2317 n = m; 2318 m = t.length(); 2319 } 2320 2321 final int[] p = new int[n + 1]; 2322 // indexes into strings s and t 2323 int i; // iterates through s 2324 int j; // iterates through t 2325 int upper_left; 2326 int upper; 2327 2328 char t_j; // jth character of t 2329 int cost; 2330 2331 for (i = 0; i <= n; i++) { 2332 p[i] = i; 2333 } 2334 2335 for (j = 1; j <= m; j++) { 2336 upper_left = p[0]; 2337 t_j = t.charAt(j - 1); 2338 p[0] = j; 2339 2340 for (i = 1; i <= n; i++) { 2341 upper = p[i]; 2342 cost = s.charAt(i - 1) == t_j ? 0 : 1; 2343 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2344 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upper_left + cost); 2345 upper_left = upper; 2346 } 2347 } 2348 2349 return p[n]; 2350 } 2351 2352 /** 2353 * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given 2354 * threshold.</p> 2355 * 2356 * <p>This is the number of changes needed to change one String into 2357 * another, where each change is a single character modification (deletion, 2358 * insertion or substitution).</p> 2359 * 2360 * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield 2361 * and Chas Emerick's implementation of the Levenshtein distance algorithm from 2362 * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> 2363 * 2364 * <pre> 2365 * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException 2366 * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException 2367 * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException 2368 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2369 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2370 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2371 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2372 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2373 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2374 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2375 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2376 * </pre> 2377 * 2378 * @param s the first String, must not be null 2379 * @param t the second String, must not be null 2380 * @param threshold the target threshold, must not be negative 2381 * @return result distance, or {@code -1} if the distance would be greater than the threshold 2382 * @throws IllegalArgumentException if either String input {@code null} or negative threshold 2383 * @deprecated as of 3.6, use commons-text 2384 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2385 * LevenshteinDistance</a> instead 2386 */ 2387 @Deprecated 2388 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2389 if (s == null || t == null) { 2390 throw new IllegalArgumentException("Strings must not be null"); 2391 } 2392 if (threshold < 0) { 2393 throw new IllegalArgumentException("Threshold must not be negative"); 2394 } 2395 2396 /* 2397 This implementation only computes the distance if it's less than or equal to the 2398 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2399 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2400 computing a diagonal stripe of width 2k + 1 of the cost table. 2401 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2402 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2403 d is the distance. 2404 2405 One subtlety comes from needing to ignore entries on the border of our stripe 2406 eg. 2407 p[] = |#|#|#|* 2408 d[] = *|#|#|#| 2409 We must ignore the entry to the left of the leftmost member 2410 We must ignore the entry above the rightmost member 2411 2412 Another subtlety comes from our stripe running off the matrix if the strings aren't 2413 of the same size. Since string s is always swapped to be the shorter of the two, 2414 the stripe will always run off to the upper right instead of the lower left of the matrix. 2415 2416 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2417 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2418 2419 1 2 3 4 5 2420 1 |#|#| | | | 2421 2 |#|#|#| | | 2422 3 | |#|#|#| | 2423 4 | | |#|#|#| 2424 5 | | | |#|#| 2425 6 | | | | |#| 2426 7 | | | | | | 2427 2428 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2429 into one of length 7 in edit distance of 1. 2430 2431 Additionally, this implementation decreases memory usage by using two 2432 single-dimensional arrays and swapping them back and forth instead of allocating 2433 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2434 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2435 large values so that entries we don't compute are ignored. 2436 2437 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2438 */ 2439 2440 int n = s.length(); // length of s 2441 int m = t.length(); // length of t 2442 2443 // if one string is empty, the edit distance is necessarily the length of the other 2444 if (n == 0) { 2445 return m <= threshold ? m : -1; 2446 } else if (m == 0) { 2447 return n <= threshold ? n : -1; 2448 } else if (Math.abs(n - m) > threshold) { 2449 // no need to calculate the distance if the length difference is greater than the threshold 2450 return -1; 2451 } 2452 2453 if (n > m) { 2454 // swap the two strings to consume less memory 2455 final CharSequence tmp = s; 2456 s = t; 2457 t = tmp; 2458 n = m; 2459 m = t.length(); 2460 } 2461 2462 int[] p = new int[n + 1]; // 'previous' cost array, horizontally 2463 int[] d = new int[n + 1]; // cost array, horizontally 2464 int[] _d; // placeholder to assist in swapping p and d 2465 2466 // fill in starting table values 2467 final int boundary = Math.min(n, threshold) + 1; 2468 for (int i = 0; i < boundary; i++) { 2469 p[i] = i; 2470 } 2471 // these fills ensure that the value above the rightmost entry of our 2472 // stripe will be ignored in following loop iterations 2473 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2474 Arrays.fill(d, Integer.MAX_VALUE); 2475 2476 // iterates through t 2477 for (int j = 1; j <= m; j++) { 2478 final char t_j = t.charAt(j - 1); // jth character of t 2479 d[0] = j; 2480 2481 // compute stripe indices, constrain to array size 2482 final int min = Math.max(1, j - threshold); 2483 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2484 2485 // the stripe may lead off of the table if s and t are of different sizes 2486 if (min > max) { 2487 return -1; 2488 } 2489 2490 // ignore entry left of leftmost 2491 if (min > 1) { 2492 d[min - 1] = Integer.MAX_VALUE; 2493 } 2494 2495 // iterates through [min, max] in s 2496 for (int i = min; i <= max; i++) { 2497 if (s.charAt(i - 1) == t_j) { 2498 // diagonally left and up 2499 d[i] = p[i - 1]; 2500 } else { 2501 // 1 + minimum of cell to the left, to the top, diagonally left and up 2502 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2503 } 2504 } 2505 2506 // copy current distance counts to 'previous row' distance counts 2507 _d = p; 2508 p = d; 2509 d = _d; 2510 } 2511 2512 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2513 // distance 2514 if (p[n] <= threshold) { 2515 return p[n]; 2516 } 2517 return -1; 2518 } 2519 2520 /** 2521 * <p>Finds the first index within a CharSequence, handling {@code null}. 2522 * This method uses {@link String#indexOf(String, int)} if possible.</p> 2523 * 2524 * <p>A {@code null} CharSequence will return {@code -1}.</p> 2525 * 2526 * <pre> 2527 * StringUtils.indexOf(null, *) = -1 2528 * StringUtils.indexOf(*, null) = -1 2529 * StringUtils.indexOf("", "") = 0 2530 * StringUtils.indexOf("", *) = -1 (except when * = "") 2531 * StringUtils.indexOf("aabaabaa", "a") = 0 2532 * StringUtils.indexOf("aabaabaa", "b") = 2 2533 * StringUtils.indexOf("aabaabaa", "ab") = 1 2534 * StringUtils.indexOf("aabaabaa", "") = 0 2535 * </pre> 2536 * 2537 * @param seq the CharSequence to check, may be null 2538 * @param searchSeq the CharSequence to find, may be null 2539 * @return the first index of the search CharSequence, 2540 * -1 if no match or {@code null} string input 2541 * @since 2.0 2542 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2543 */ 2544 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2545 if (seq == null || searchSeq == null) { 2546 return INDEX_NOT_FOUND; 2547 } 2548 return CharSequenceUtils.indexOf(seq, searchSeq, 0); 2549 } 2550 2551 /** 2552 * <p>Finds the first index within a CharSequence, handling {@code null}. 2553 * This method uses {@link String#indexOf(String, int)} if possible.</p> 2554 * 2555 * <p>A {@code null} CharSequence will return {@code -1}. 2556 * A negative start position is treated as zero. 2557 * An empty ("") search CharSequence always matches. 2558 * A start position greater than the string length only matches 2559 * an empty search CharSequence.</p> 2560 * 2561 * <pre> 2562 * StringUtils.indexOf(null, *, *) = -1 2563 * StringUtils.indexOf(*, null, *) = -1 2564 * StringUtils.indexOf("", "", 0) = 0 2565 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2566 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2567 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2568 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2569 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2570 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2571 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2572 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2573 * StringUtils.indexOf("abc", "", 9) = 3 2574 * </pre> 2575 * 2576 * @param seq the CharSequence to check, may be null 2577 * @param searchSeq the CharSequence to find, may be null 2578 * @param startPos the start position, negative treated as zero 2579 * @return the first index of the search CharSequence (always ≥ startPos), 2580 * -1 if no match or {@code null} string input 2581 * @since 2.0 2582 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2583 */ 2584 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2585 if (seq == null || searchSeq == null) { 2586 return INDEX_NOT_FOUND; 2587 } 2588 return CharSequenceUtils.indexOf(seq, searchSeq, startPos); 2589 } 2590 2591 // IndexOf 2592 //----------------------------------------------------------------------- 2593 /** 2594 * Returns the index within {@code seq} of the first occurrence of 2595 * the specified character. If a character with value 2596 * {@code searchChar} occurs in the character sequence represented by 2597 * {@code seq} {@code CharSequence} object, then the index (in Unicode 2598 * code units) of the first such occurrence is returned. For 2599 * values of {@code searchChar} in the range from 0 to 0xFFFF 2600 * (inclusive), this is the smallest value <i>k</i> such that: 2601 * <blockquote><pre> 2602 * this.charAt(<i>k</i>) == searchChar 2603 * </pre></blockquote> 2604 * is true. For other values of {@code searchChar}, it is the 2605 * smallest value <i>k</i> such that: 2606 * <blockquote><pre> 2607 * this.codePointAt(<i>k</i>) == searchChar 2608 * </pre></blockquote> 2609 * is true. In either case, if no such character occurs in {@code seq}, 2610 * then {@code INDEX_NOT_FOUND (-1)} is returned. 2611 * 2612 * <p>Furthermore, a {@code null} or empty ("") CharSequence will 2613 * return {@code INDEX_NOT_FOUND (-1)}.</p> 2614 * 2615 * <pre> 2616 * StringUtils.indexOf(null, *) = -1 2617 * StringUtils.indexOf("", *) = -1 2618 * StringUtils.indexOf("aabaabaa", 'a') = 0 2619 * StringUtils.indexOf("aabaabaa", 'b') = 2 2620 * </pre> 2621 * 2622 * @param seq the CharSequence to check, may be null 2623 * @param searchChar the character to find 2624 * @return the first index of the search character, 2625 * -1 if no match or {@code null} string input 2626 * @since 2.0 2627 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2628 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String} 2629 */ 2630 public static int indexOf(final CharSequence seq, final int searchChar) { 2631 if (isEmpty(seq)) { 2632 return INDEX_NOT_FOUND; 2633 } 2634 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2635 } 2636 2637 /** 2638 * 2639 * Returns the index within {@code seq} of the first occurrence of the 2640 * specified character, starting the search at the specified index. 2641 * <p> 2642 * If a character with value {@code searchChar} occurs in the 2643 * character sequence represented by the {@code seq} {@code CharSequence} 2644 * object at an index no smaller than {@code startPos}, then 2645 * the index of the first such occurrence is returned. For values 2646 * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), 2647 * this is the smallest value <i>k</i> such that: 2648 * <blockquote><pre> 2649 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2650 * </pre></blockquote> 2651 * is true. For other values of {@code searchChar}, it is the 2652 * smallest value <i>k</i> such that: 2653 * <blockquote><pre> 2654 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2655 * </pre></blockquote> 2656 * is true. In either case, if no such character occurs in {@code seq} 2657 * at or after position {@code startPos}, then 2658 * {@code -1} is returned. 2659 * 2660 * <p> 2661 * There is no restriction on the value of {@code startPos}. If it 2662 * is negative, it has the same effect as if it were zero: this entire 2663 * string may be searched. If it is greater than the length of this 2664 * string, it has the same effect as if it were equal to the length of 2665 * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a 2666 * {@code null} or empty ("") CharSequence will 2667 * return {@code (INDEX_NOT_FOUND) -1}. 2668 * 2669 * <p>All indices are specified in {@code char} values 2670 * (Unicode code units). 2671 * 2672 * <pre> 2673 * StringUtils.indexOf(null, *, *) = -1 2674 * StringUtils.indexOf("", *, *) = -1 2675 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2676 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2677 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2678 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2679 * </pre> 2680 * 2681 * @param seq the CharSequence to check, may be null 2682 * @param searchChar the character to find 2683 * @param startPos the start position, negative treated as zero 2684 * @return the first index of the search character (always ≥ startPos), 2685 * -1 if no match or {@code null} string input 2686 * @since 2.0 2687 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2688 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String} 2689 */ 2690 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2691 if (isEmpty(seq)) { 2692 return INDEX_NOT_FOUND; 2693 } 2694 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2695 } 2696 2697 // IndexOfAny chars 2698 //----------------------------------------------------------------------- 2699 /** 2700 * <p>Search a CharSequence to find the first index of any 2701 * character in the given set of characters.</p> 2702 * 2703 * <p>A {@code null} String will return {@code -1}. 2704 * A {@code null} or zero length search array will return {@code -1}.</p> 2705 * 2706 * <pre> 2707 * StringUtils.indexOfAny(null, *) = -1 2708 * StringUtils.indexOfAny("", *) = -1 2709 * StringUtils.indexOfAny(*, null) = -1 2710 * StringUtils.indexOfAny(*, []) = -1 2711 * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0 2712 * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3 2713 * StringUtils.indexOfAny("aba", ['z']) = -1 2714 * </pre> 2715 * 2716 * @param cs the CharSequence to check, may be null 2717 * @param searchChars the chars to search for, may be null 2718 * @return the index of any of the chars, -1 if no match or null input 2719 * @since 2.0 2720 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2721 */ 2722 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2723 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2724 return INDEX_NOT_FOUND; 2725 } 2726 final int csLen = cs.length(); 2727 final int csLast = csLen - 1; 2728 final int searchLen = searchChars.length; 2729 final int searchLast = searchLen - 1; 2730 for (int i = 0; i < csLen; i++) { 2731 final char ch = cs.charAt(i); 2732 for (int j = 0; j < searchLen; j++) { 2733 if (searchChars[j] == ch) { 2734 if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) { 2735 // ch is a supplementary character 2736 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2737 return i; 2738 } 2739 } else { 2740 return i; 2741 } 2742 } 2743 } 2744 } 2745 return INDEX_NOT_FOUND; 2746 } 2747 2748 // IndexOfAny strings 2749 //----------------------------------------------------------------------- 2750 /** 2751 * <p>Find the first index of any of a set of potential substrings.</p> 2752 * 2753 * <p>A {@code null} CharSequence will return {@code -1}. 2754 * A {@code null} or zero length search array will return {@code -1}. 2755 * A {@code null} search array entry will be ignored, but a search 2756 * array containing "" will return {@code 0} if {@code str} is not 2757 * null. This method uses {@link String#indexOf(String)} if possible.</p> 2758 * 2759 * <pre> 2760 * StringUtils.indexOfAny(null, *) = -1 2761 * StringUtils.indexOfAny(*, null) = -1 2762 * StringUtils.indexOfAny(*, []) = -1 2763 * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"]) = 2 2764 * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"]) = 2 2765 * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"]) = -1 2766 * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1 2767 * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0 2768 * StringUtils.indexOfAny("", [""]) = 0 2769 * StringUtils.indexOfAny("", ["a"]) = -1 2770 * </pre> 2771 * 2772 * @param str the CharSequence to check, may be null 2773 * @param searchStrs the CharSequences to search for, may be null 2774 * @return the first index of any of the searchStrs in str, -1 if no match 2775 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2776 */ 2777 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2778 if (str == null || searchStrs == null) { 2779 return INDEX_NOT_FOUND; 2780 } 2781 2782 // String's can't have a MAX_VALUEth index. 2783 int ret = Integer.MAX_VALUE; 2784 2785 int tmp = 0; 2786 for (final CharSequence search : searchStrs) { 2787 if (search == null) { 2788 continue; 2789 } 2790 tmp = CharSequenceUtils.indexOf(str, search, 0); 2791 if (tmp == INDEX_NOT_FOUND) { 2792 continue; 2793 } 2794 2795 if (tmp < ret) { 2796 ret = tmp; 2797 } 2798 } 2799 2800 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2801 } 2802 2803 /** 2804 * <p>Search a CharSequence to find the first index of any 2805 * character in the given set of characters.</p> 2806 * 2807 * <p>A {@code null} String will return {@code -1}. 2808 * A {@code null} search string will return {@code -1}.</p> 2809 * 2810 * <pre> 2811 * StringUtils.indexOfAny(null, *) = -1 2812 * StringUtils.indexOfAny("", *) = -1 2813 * StringUtils.indexOfAny(*, null) = -1 2814 * StringUtils.indexOfAny(*, "") = -1 2815 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2816 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2817 * StringUtils.indexOfAny("aba", "z") = -1 2818 * </pre> 2819 * 2820 * @param cs the CharSequence to check, may be null 2821 * @param searchChars the chars to search for, may be null 2822 * @return the index of any of the chars, -1 if no match or null input 2823 * @since 2.0 2824 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2825 */ 2826 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2827 if (isEmpty(cs) || isEmpty(searchChars)) { 2828 return INDEX_NOT_FOUND; 2829 } 2830 return indexOfAny(cs, searchChars.toCharArray()); 2831 } 2832 2833 // IndexOfAnyBut chars 2834 //----------------------------------------------------------------------- 2835 /** 2836 * <p>Searches a CharSequence to find the first index of any 2837 * character not in the given set of characters.</p> 2838 * 2839 * <p>A {@code null} CharSequence will return {@code -1}. 2840 * A {@code null} or zero length search array will return {@code -1}.</p> 2841 * 2842 * <pre> 2843 * StringUtils.indexOfAnyBut(null, *) = -1 2844 * StringUtils.indexOfAnyBut("", *) = -1 2845 * StringUtils.indexOfAnyBut(*, null) = -1 2846 * StringUtils.indexOfAnyBut(*, []) = -1 2847 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2848 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2849 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2850 2851 * </pre> 2852 * 2853 * @param cs the CharSequence to check, may be null 2854 * @param searchChars the chars to search for, may be null 2855 * @return the index of any of the chars, -1 if no match or null input 2856 * @since 2.0 2857 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2858 */ 2859 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2860 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2861 return INDEX_NOT_FOUND; 2862 } 2863 final int csLen = cs.length(); 2864 final int csLast = csLen - 1; 2865 final int searchLen = searchChars.length; 2866 final int searchLast = searchLen - 1; 2867 outer: 2868 for (int i = 0; i < csLen; i++) { 2869 final char ch = cs.charAt(i); 2870 for (int j = 0; j < searchLen; j++) { 2871 if (searchChars[j] == ch) { 2872 if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) { 2873 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2874 continue outer; 2875 } 2876 } else { 2877 continue outer; 2878 } 2879 } 2880 } 2881 return i; 2882 } 2883 return INDEX_NOT_FOUND; 2884 } 2885 2886 /** 2887 * <p>Search a CharSequence to find the first index of any 2888 * character not in the given set of characters.</p> 2889 * 2890 * <p>A {@code null} CharSequence will return {@code -1}. 2891 * A {@code null} or empty search string will return {@code -1}.</p> 2892 * 2893 * <pre> 2894 * StringUtils.indexOfAnyBut(null, *) = -1 2895 * StringUtils.indexOfAnyBut("", *) = -1 2896 * StringUtils.indexOfAnyBut(*, null) = -1 2897 * StringUtils.indexOfAnyBut(*, "") = -1 2898 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2899 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2900 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2901 * </pre> 2902 * 2903 * @param seq the CharSequence to check, may be null 2904 * @param searchChars the chars to search for, may be null 2905 * @return the index of any of the chars, -1 if no match or null input 2906 * @since 2.0 2907 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2908 */ 2909 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2910 if (isEmpty(seq) || isEmpty(searchChars)) { 2911 return INDEX_NOT_FOUND; 2912 } 2913 final int strLen = seq.length(); 2914 for (int i = 0; i < strLen; i++) { 2915 final char ch = seq.charAt(i); 2916 final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0; 2917 if (i + 1 < strLen && Character.isHighSurrogate(ch)) { 2918 final char ch2 = seq.charAt(i + 1); 2919 if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) { 2920 return i; 2921 } 2922 } else { 2923 if (!chFound) { 2924 return i; 2925 } 2926 } 2927 } 2928 return INDEX_NOT_FOUND; 2929 } 2930 2931 /** 2932 * <p>Compares all CharSequences in an array and returns the index at which the 2933 * CharSequences begin to differ.</p> 2934 * 2935 * <p>For example, 2936 * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p> 2937 * 2938 * <pre> 2939 * StringUtils.indexOfDifference(null) = -1 2940 * StringUtils.indexOfDifference(new String[] {}) = -1 2941 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 2942 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 2943 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 2944 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 2945 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 2946 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 2947 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 2948 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 2949 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 2950 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 2951 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 2952 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 2953 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 2954 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 2955 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 2956 * </pre> 2957 * 2958 * @param css array of CharSequences, entries may be null 2959 * @return the index where the strings begin to differ; -1 if they are all equal 2960 * @since 2.4 2961 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 2962 */ 2963 public static int indexOfDifference(final CharSequence... css) { 2964 if (ArrayUtils.getLength(css) <= 1) { 2965 return INDEX_NOT_FOUND; 2966 } 2967 boolean anyStringNull = false; 2968 boolean allStringsNull = true; 2969 final int arrayLen = css.length; 2970 int shortestStrLen = Integer.MAX_VALUE; 2971 int longestStrLen = 0; 2972 2973 // find the min and max string lengths; this avoids checking to make 2974 // sure we are not exceeding the length of the string each time through 2975 // the bottom loop. 2976 for (final CharSequence cs : css) { 2977 if (cs == null) { 2978 anyStringNull = true; 2979 shortestStrLen = 0; 2980 } else { 2981 allStringsNull = false; 2982 shortestStrLen = Math.min(cs.length(), shortestStrLen); 2983 longestStrLen = Math.max(cs.length(), longestStrLen); 2984 } 2985 } 2986 2987 // handle lists containing all nulls or all empty strings 2988 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 2989 return INDEX_NOT_FOUND; 2990 } 2991 2992 // handle lists containing some nulls or some empty strings 2993 if (shortestStrLen == 0) { 2994 return 0; 2995 } 2996 2997 // find the position with the first difference across all strings 2998 int firstDiff = -1; 2999 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 3000 final char comparisonChar = css[0].charAt(stringPos); 3001 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 3002 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 3003 firstDiff = stringPos; 3004 break; 3005 } 3006 } 3007 if (firstDiff != -1) { 3008 break; 3009 } 3010 } 3011 3012 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 3013 // we compared all of the characters up to the length of the 3014 // shortest string and didn't find a match, but the string lengths 3015 // vary, so return the length of the shortest string. 3016 return shortestStrLen; 3017 } 3018 return firstDiff; 3019 } 3020 3021 /** 3022 * <p>Compares two CharSequences, and returns the index at which the 3023 * CharSequences begin to differ.</p> 3024 * 3025 * <p>For example, 3026 * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p> 3027 * 3028 * <pre> 3029 * StringUtils.indexOfDifference(null, null) = -1 3030 * StringUtils.indexOfDifference("", "") = -1 3031 * StringUtils.indexOfDifference("", "abc") = 0 3032 * StringUtils.indexOfDifference("abc", "") = 0 3033 * StringUtils.indexOfDifference("abc", "abc") = -1 3034 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3035 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3036 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3037 * </pre> 3038 * 3039 * @param cs1 the first CharSequence, may be null 3040 * @param cs2 the second CharSequence, may be null 3041 * @return the index where cs1 and cs2 begin to differ; -1 if they are equal 3042 * @since 2.0 3043 * @since 3.0 Changed signature from indexOfDifference(String, String) to 3044 * indexOfDifference(CharSequence, CharSequence) 3045 */ 3046 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3047 if (cs1 == cs2) { 3048 return INDEX_NOT_FOUND; 3049 } 3050 if (cs1 == null || cs2 == null) { 3051 return 0; 3052 } 3053 int i; 3054 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3055 if (cs1.charAt(i) != cs2.charAt(i)) { 3056 break; 3057 } 3058 } 3059 if (i < cs2.length() || i < cs1.length()) { 3060 return i; 3061 } 3062 return INDEX_NOT_FOUND; 3063 } 3064 3065 /** 3066 * <p>Case in-sensitive find of the first index within a CharSequence.</p> 3067 * 3068 * <p>A {@code null} CharSequence will return {@code -1}. 3069 * A negative start position is treated as zero. 3070 * An empty ("") search CharSequence always matches. 3071 * A start position greater than the string length only matches 3072 * an empty search CharSequence.</p> 3073 * 3074 * <pre> 3075 * StringUtils.indexOfIgnoreCase(null, *) = -1 3076 * StringUtils.indexOfIgnoreCase(*, null) = -1 3077 * StringUtils.indexOfIgnoreCase("", "") = 0 3078 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3079 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3080 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3081 * </pre> 3082 * 3083 * @param str the CharSequence to check, may be null 3084 * @param searchStr the CharSequence to find, may be null 3085 * @return the first index of the search CharSequence, 3086 * -1 if no match or {@code null} string input 3087 * @since 2.5 3088 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3089 */ 3090 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3091 return indexOfIgnoreCase(str, searchStr, 0); 3092 } 3093 3094 /** 3095 * <p>Case in-sensitive find of the first index within a CharSequence 3096 * from the specified position.</p> 3097 * 3098 * <p>A {@code null} CharSequence will return {@code -1}. 3099 * A negative start position is treated as zero. 3100 * An empty ("") search CharSequence always matches. 3101 * A start position greater than the string length only matches 3102 * an empty search CharSequence.</p> 3103 * 3104 * <pre> 3105 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3106 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3107 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3108 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3109 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3110 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3111 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3112 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3113 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3114 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3115 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3116 * </pre> 3117 * 3118 * @param str the CharSequence to check, may be null 3119 * @param searchStr the CharSequence to find, may be null 3120 * @param startPos the start position, negative treated as zero 3121 * @return the first index of the search CharSequence (always ≥ startPos), 3122 * -1 if no match or {@code null} string input 3123 * @since 2.5 3124 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3125 */ 3126 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 3127 if (str == null || searchStr == null) { 3128 return INDEX_NOT_FOUND; 3129 } 3130 if (startPos < 0) { 3131 startPos = 0; 3132 } 3133 final int endLimit = str.length() - searchStr.length() + 1; 3134 if (startPos > endLimit) { 3135 return INDEX_NOT_FOUND; 3136 } 3137 if (searchStr.length() == 0) { 3138 return startPos; 3139 } 3140 for (int i = startPos; i < endLimit; i++) { 3141 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 3142 return i; 3143 } 3144 } 3145 return INDEX_NOT_FOUND; 3146 } 3147 3148 /** 3149 * <p>Checks if all of the CharSequences are empty (""), null or whitespace only.</p> 3150 * 3151 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3152 * 3153 * <pre> 3154 * StringUtils.isAllBlank(null) = true 3155 * StringUtils.isAllBlank(null, "foo") = false 3156 * StringUtils.isAllBlank(null, null) = true 3157 * StringUtils.isAllBlank("", "bar") = false 3158 * StringUtils.isAllBlank("bob", "") = false 3159 * StringUtils.isAllBlank(" bob ", null) = false 3160 * StringUtils.isAllBlank(" ", "bar") = false 3161 * StringUtils.isAllBlank("foo", "bar") = false 3162 * StringUtils.isAllBlank(new String[] {}) = true 3163 * </pre> 3164 * 3165 * @param css the CharSequences to check, may be null or empty 3166 * @return {@code true} if all of the CharSequences are empty or null or whitespace only 3167 * @since 3.6 3168 */ 3169 public static boolean isAllBlank(final CharSequence... css) { 3170 if (ArrayUtils.isEmpty(css)) { 3171 return true; 3172 } 3173 for (final CharSequence cs : css) { 3174 if (isNotBlank(cs)) { 3175 return false; 3176 } 3177 } 3178 return true; 3179 } 3180 3181 /** 3182 * <p>Checks if all of the CharSequences are empty ("") or null.</p> 3183 * 3184 * <pre> 3185 * StringUtils.isAllEmpty(null) = true 3186 * StringUtils.isAllEmpty(null, "") = true 3187 * StringUtils.isAllEmpty(new String[] {}) = true 3188 * StringUtils.isAllEmpty(null, "foo") = false 3189 * StringUtils.isAllEmpty("", "bar") = false 3190 * StringUtils.isAllEmpty("bob", "") = false 3191 * StringUtils.isAllEmpty(" bob ", null) = false 3192 * StringUtils.isAllEmpty(" ", "bar") = false 3193 * StringUtils.isAllEmpty("foo", "bar") = false 3194 * </pre> 3195 * 3196 * @param css the CharSequences to check, may be null or empty 3197 * @return {@code true} if all of the CharSequences are empty or null 3198 * @since 3.6 3199 */ 3200 public static boolean isAllEmpty(final CharSequence... css) { 3201 if (ArrayUtils.isEmpty(css)) { 3202 return true; 3203 } 3204 for (final CharSequence cs : css) { 3205 if (isNotEmpty(cs)) { 3206 return false; 3207 } 3208 } 3209 return true; 3210 } 3211 3212 /** 3213 * <p>Checks if the CharSequence contains only lowercase characters.</p> 3214 * 3215 * <p>{@code null} will return {@code false}. 3216 * An empty CharSequence (length()=0) will return {@code false}.</p> 3217 * 3218 * <pre> 3219 * StringUtils.isAllLowerCase(null) = false 3220 * StringUtils.isAllLowerCase("") = false 3221 * StringUtils.isAllLowerCase(" ") = false 3222 * StringUtils.isAllLowerCase("abc") = true 3223 * StringUtils.isAllLowerCase("abC") = false 3224 * StringUtils.isAllLowerCase("ab c") = false 3225 * StringUtils.isAllLowerCase("ab1c") = false 3226 * StringUtils.isAllLowerCase("ab/c") = false 3227 * </pre> 3228 * 3229 * @param cs the CharSequence to check, may be null 3230 * @return {@code true} if only contains lowercase characters, and is non-null 3231 * @since 2.5 3232 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3233 */ 3234 public static boolean isAllLowerCase(final CharSequence cs) { 3235 if (isEmpty(cs)) { 3236 return false; 3237 } 3238 final int sz = cs.length(); 3239 for (int i = 0; i < sz; i++) { 3240 if (!Character.isLowerCase(cs.charAt(i))) { 3241 return false; 3242 } 3243 } 3244 return true; 3245 } 3246 3247 /** 3248 * <p>Checks if the CharSequence contains only uppercase characters.</p> 3249 * 3250 * <p>{@code null} will return {@code false}. 3251 * An empty String (length()=0) will return {@code false}.</p> 3252 * 3253 * <pre> 3254 * StringUtils.isAllUpperCase(null) = false 3255 * StringUtils.isAllUpperCase("") = false 3256 * StringUtils.isAllUpperCase(" ") = false 3257 * StringUtils.isAllUpperCase("ABC") = true 3258 * StringUtils.isAllUpperCase("aBC") = false 3259 * StringUtils.isAllUpperCase("A C") = false 3260 * StringUtils.isAllUpperCase("A1C") = false 3261 * StringUtils.isAllUpperCase("A/C") = false 3262 * </pre> 3263 * 3264 * @param cs the CharSequence to check, may be null 3265 * @return {@code true} if only contains uppercase characters, and is non-null 3266 * @since 2.5 3267 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3268 */ 3269 public static boolean isAllUpperCase(final CharSequence cs) { 3270 if (isEmpty(cs)) { 3271 return false; 3272 } 3273 final int sz = cs.length(); 3274 for (int i = 0; i < sz; i++) { 3275 if (!Character.isUpperCase(cs.charAt(i))) { 3276 return false; 3277 } 3278 } 3279 return true; 3280 } 3281 3282 // Character Tests 3283 //----------------------------------------------------------------------- 3284 /** 3285 * <p>Checks if the CharSequence contains only Unicode letters.</p> 3286 * 3287 * <p>{@code null} will return {@code false}. 3288 * An empty CharSequence (length()=0) will return {@code false}.</p> 3289 * 3290 * <pre> 3291 * StringUtils.isAlpha(null) = false 3292 * StringUtils.isAlpha("") = false 3293 * StringUtils.isAlpha(" ") = false 3294 * StringUtils.isAlpha("abc") = true 3295 * StringUtils.isAlpha("ab2c") = false 3296 * StringUtils.isAlpha("ab-c") = false 3297 * </pre> 3298 * 3299 * @param cs the CharSequence to check, may be null 3300 * @return {@code true} if only contains letters, and is non-null 3301 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3302 * @since 3.0 Changed "" to return false and not true 3303 */ 3304 public static boolean isAlpha(final CharSequence cs) { 3305 if (isEmpty(cs)) { 3306 return false; 3307 } 3308 final int sz = cs.length(); 3309 for (int i = 0; i < sz; i++) { 3310 if (!Character.isLetter(cs.charAt(i))) { 3311 return false; 3312 } 3313 } 3314 return true; 3315 } 3316 3317 /** 3318 * <p>Checks if the CharSequence contains only Unicode letters or digits.</p> 3319 * 3320 * <p>{@code null} will return {@code false}. 3321 * An empty CharSequence (length()=0) will return {@code false}.</p> 3322 * 3323 * <pre> 3324 * StringUtils.isAlphanumeric(null) = false 3325 * StringUtils.isAlphanumeric("") = false 3326 * StringUtils.isAlphanumeric(" ") = false 3327 * StringUtils.isAlphanumeric("abc") = true 3328 * StringUtils.isAlphanumeric("ab c") = false 3329 * StringUtils.isAlphanumeric("ab2c") = true 3330 * StringUtils.isAlphanumeric("ab-c") = false 3331 * </pre> 3332 * 3333 * @param cs the CharSequence to check, may be null 3334 * @return {@code true} if only contains letters or digits, 3335 * and is non-null 3336 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3337 * @since 3.0 Changed "" to return false and not true 3338 */ 3339 public static boolean isAlphanumeric(final CharSequence cs) { 3340 if (isEmpty(cs)) { 3341 return false; 3342 } 3343 final int sz = cs.length(); 3344 for (int i = 0; i < sz; i++) { 3345 if (!Character.isLetterOrDigit(cs.charAt(i))) { 3346 return false; 3347 } 3348 } 3349 return true; 3350 } 3351 3352 /** 3353 * <p>Checks if the CharSequence contains only Unicode letters, digits 3354 * or space ({@code ' '}).</p> 3355 * 3356 * <p>{@code null} will return {@code false}. 3357 * An empty CharSequence (length()=0) will return {@code true}.</p> 3358 * 3359 * <pre> 3360 * StringUtils.isAlphanumericSpace(null) = false 3361 * StringUtils.isAlphanumericSpace("") = true 3362 * StringUtils.isAlphanumericSpace(" ") = true 3363 * StringUtils.isAlphanumericSpace("abc") = true 3364 * StringUtils.isAlphanumericSpace("ab c") = true 3365 * StringUtils.isAlphanumericSpace("ab2c") = true 3366 * StringUtils.isAlphanumericSpace("ab-c") = false 3367 * </pre> 3368 * 3369 * @param cs the CharSequence to check, may be null 3370 * @return {@code true} if only contains letters, digits or space, 3371 * and is non-null 3372 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3373 */ 3374 public static boolean isAlphanumericSpace(final CharSequence cs) { 3375 if (cs == null) { 3376 return false; 3377 } 3378 final int sz = cs.length(); 3379 for (int i = 0; i < sz; i++) { 3380 if (!Character.isLetterOrDigit(cs.charAt(i)) && cs.charAt(i) != ' ') { 3381 return false; 3382 } 3383 } 3384 return true; 3385 } 3386 3387 /** 3388 * <p>Checks if the CharSequence contains only Unicode letters and 3389 * space (' ').</p> 3390 * 3391 * <p>{@code null} will return {@code false} 3392 * An empty CharSequence (length()=0) will return {@code true}.</p> 3393 * 3394 * <pre> 3395 * StringUtils.isAlphaSpace(null) = false 3396 * StringUtils.isAlphaSpace("") = true 3397 * StringUtils.isAlphaSpace(" ") = true 3398 * StringUtils.isAlphaSpace("abc") = true 3399 * StringUtils.isAlphaSpace("ab c") = true 3400 * StringUtils.isAlphaSpace("ab2c") = false 3401 * StringUtils.isAlphaSpace("ab-c") = false 3402 * </pre> 3403 * 3404 * @param cs the CharSequence to check, may be null 3405 * @return {@code true} if only contains letters and space, 3406 * and is non-null 3407 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3408 */ 3409 public static boolean isAlphaSpace(final CharSequence cs) { 3410 if (cs == null) { 3411 return false; 3412 } 3413 final int sz = cs.length(); 3414 for (int i = 0; i < sz; i++) { 3415 if (!Character.isLetter(cs.charAt(i)) && cs.charAt(i) != ' ') { 3416 return false; 3417 } 3418 } 3419 return true; 3420 } 3421 3422 /** 3423 * <p>Checks if any of the CharSequences are empty ("") or null or whitespace only.</p> 3424 * 3425 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3426 * 3427 * <pre> 3428 * StringUtils.isAnyBlank((String) null) = true 3429 * StringUtils.isAnyBlank((String[]) null) = false 3430 * StringUtils.isAnyBlank(null, "foo") = true 3431 * StringUtils.isAnyBlank(null, null) = true 3432 * StringUtils.isAnyBlank("", "bar") = true 3433 * StringUtils.isAnyBlank("bob", "") = true 3434 * StringUtils.isAnyBlank(" bob ", null) = true 3435 * StringUtils.isAnyBlank(" ", "bar") = true 3436 * StringUtils.isAnyBlank(new String[] {}) = false 3437 * StringUtils.isAnyBlank(new String[]{""}) = true 3438 * StringUtils.isAnyBlank("foo", "bar") = false 3439 * </pre> 3440 * 3441 * @param css the CharSequences to check, may be null or empty 3442 * @return {@code true} if any of the CharSequences are empty or null or whitespace only 3443 * @since 3.2 3444 */ 3445 public static boolean isAnyBlank(final CharSequence... css) { 3446 if (ArrayUtils.isEmpty(css)) { 3447 return false; 3448 } 3449 for (final CharSequence cs : css) { 3450 if (isBlank(cs)) { 3451 return true; 3452 } 3453 } 3454 return false; 3455 } 3456 3457 /** 3458 * <p>Checks if any of the CharSequences are empty ("") or null.</p> 3459 * 3460 * <pre> 3461 * StringUtils.isAnyEmpty((String) null) = true 3462 * StringUtils.isAnyEmpty((String[]) null) = false 3463 * StringUtils.isAnyEmpty(null, "foo") = true 3464 * StringUtils.isAnyEmpty("", "bar") = true 3465 * StringUtils.isAnyEmpty("bob", "") = true 3466 * StringUtils.isAnyEmpty(" bob ", null) = true 3467 * StringUtils.isAnyEmpty(" ", "bar") = false 3468 * StringUtils.isAnyEmpty("foo", "bar") = false 3469 * StringUtils.isAnyEmpty(new String[]{}) = false 3470 * StringUtils.isAnyEmpty(new String[]{""}) = true 3471 * </pre> 3472 * 3473 * @param css the CharSequences to check, may be null or empty 3474 * @return {@code true} if any of the CharSequences are empty or null 3475 * @since 3.2 3476 */ 3477 public static boolean isAnyEmpty(final CharSequence... css) { 3478 if (ArrayUtils.isEmpty(css)) { 3479 return false; 3480 } 3481 for (final CharSequence cs : css) { 3482 if (isEmpty(cs)) { 3483 return true; 3484 } 3485 } 3486 return false; 3487 } 3488 3489 /** 3490 * <p>Checks if the CharSequence contains only ASCII printable characters.</p> 3491 * 3492 * <p>{@code null} will return {@code false}. 3493 * An empty CharSequence (length()=0) will return {@code true}.</p> 3494 * 3495 * <pre> 3496 * StringUtils.isAsciiPrintable(null) = false 3497 * StringUtils.isAsciiPrintable("") = true 3498 * StringUtils.isAsciiPrintable(" ") = true 3499 * StringUtils.isAsciiPrintable("Ceki") = true 3500 * StringUtils.isAsciiPrintable("ab2c") = true 3501 * StringUtils.isAsciiPrintable("!ab-c~") = true 3502 * StringUtils.isAsciiPrintable("\u0020") = true 3503 * StringUtils.isAsciiPrintable("\u0021") = true 3504 * StringUtils.isAsciiPrintable("\u007e") = true 3505 * StringUtils.isAsciiPrintable("\u007f") = false 3506 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3507 * </pre> 3508 * 3509 * @param cs the CharSequence to check, may be null 3510 * @return {@code true} if every character is in the range 3511 * 32 thru 126 3512 * @since 2.1 3513 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3514 */ 3515 public static boolean isAsciiPrintable(final CharSequence cs) { 3516 if (cs == null) { 3517 return false; 3518 } 3519 final int sz = cs.length(); 3520 for (int i = 0; i < sz; i++) { 3521 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3522 return false; 3523 } 3524 } 3525 return true; 3526 } 3527 3528 // Nested extraction 3529 //----------------------------------------------------------------------- 3530 3531 /** 3532 * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p> 3533 * 3534 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3535 * 3536 * <pre> 3537 * StringUtils.isBlank(null) = true 3538 * StringUtils.isBlank("") = true 3539 * StringUtils.isBlank(" ") = true 3540 * StringUtils.isBlank("bob") = false 3541 * StringUtils.isBlank(" bob ") = false 3542 * </pre> 3543 * 3544 * @param cs the CharSequence to check, may be null 3545 * @return {@code true} if the CharSequence is null, empty or whitespace only 3546 * @since 2.0 3547 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3548 */ 3549 public static boolean isBlank(final CharSequence cs) { 3550 final int strLen = length(cs); 3551 if (strLen == 0) { 3552 return true; 3553 } 3554 for (int i = 0; i < strLen; i++) { 3555 if (!Character.isWhitespace(cs.charAt(i))) { 3556 return false; 3557 } 3558 } 3559 return true; 3560 } 3561 3562 // Empty checks 3563 //----------------------------------------------------------------------- 3564 /** 3565 * <p>Checks if a CharSequence is empty ("") or null.</p> 3566 * 3567 * <pre> 3568 * StringUtils.isEmpty(null) = true 3569 * StringUtils.isEmpty("") = true 3570 * StringUtils.isEmpty(" ") = false 3571 * StringUtils.isEmpty("bob") = false 3572 * StringUtils.isEmpty(" bob ") = false 3573 * </pre> 3574 * 3575 * <p>NOTE: This method changed in Lang version 2.0. 3576 * It no longer trims the CharSequence. 3577 * That functionality is available in isBlank().</p> 3578 * 3579 * @param cs the CharSequence to check, may be null 3580 * @return {@code true} if the CharSequence is empty or null 3581 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3582 */ 3583 public static boolean isEmpty(final CharSequence cs) { 3584 return cs == null || cs.length() == 0; 3585 } 3586 3587 /** 3588 * <p>Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters.</p> 3589 * 3590 * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return 3591 * {@code false}.</p> 3592 * 3593 * <pre> 3594 * StringUtils.isMixedCase(null) = false 3595 * StringUtils.isMixedCase("") = false 3596 * StringUtils.isMixedCase("ABC") = false 3597 * StringUtils.isMixedCase("abc") = false 3598 * StringUtils.isMixedCase("aBc") = true 3599 * StringUtils.isMixedCase("A c") = true 3600 * StringUtils.isMixedCase("A1c") = true 3601 * StringUtils.isMixedCase("a/C") = true 3602 * StringUtils.isMixedCase("aC\t") = true 3603 * </pre> 3604 * 3605 * @param cs the CharSequence to check, may be null 3606 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters 3607 * @since 3.5 3608 */ 3609 public static boolean isMixedCase(final CharSequence cs) { 3610 if (isEmpty(cs) || cs.length() == 1) { 3611 return false; 3612 } 3613 boolean containsUppercase = false; 3614 boolean containsLowercase = false; 3615 final int sz = cs.length(); 3616 for (int i = 0; i < sz; i++) { 3617 if (containsUppercase && containsLowercase) { 3618 return true; 3619 } else if (Character.isUpperCase(cs.charAt(i))) { 3620 containsUppercase = true; 3621 } else if (Character.isLowerCase(cs.charAt(i))) { 3622 containsLowercase = true; 3623 } 3624 } 3625 return containsUppercase && containsLowercase; 3626 } 3627 3628 /** 3629 * <p>Checks if none of the CharSequences are empty (""), null or whitespace only.</p> 3630 * 3631 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3632 * 3633 * <pre> 3634 * StringUtils.isNoneBlank((String) null) = false 3635 * StringUtils.isNoneBlank((String[]) null) = true 3636 * StringUtils.isNoneBlank(null, "foo") = false 3637 * StringUtils.isNoneBlank(null, null) = false 3638 * StringUtils.isNoneBlank("", "bar") = false 3639 * StringUtils.isNoneBlank("bob", "") = false 3640 * StringUtils.isNoneBlank(" bob ", null) = false 3641 * StringUtils.isNoneBlank(" ", "bar") = false 3642 * StringUtils.isNoneBlank(new String[] {}) = true 3643 * StringUtils.isNoneBlank(new String[]{""}) = false 3644 * StringUtils.isNoneBlank("foo", "bar") = true 3645 * </pre> 3646 * 3647 * @param css the CharSequences to check, may be null or empty 3648 * @return {@code true} if none of the CharSequences are empty or null or whitespace only 3649 * @since 3.2 3650 */ 3651 public static boolean isNoneBlank(final CharSequence... css) { 3652 return !isAnyBlank(css); 3653 } 3654 3655 /** 3656 * <p>Checks if none of the CharSequences are empty ("") or null.</p> 3657 * 3658 * <pre> 3659 * StringUtils.isNoneEmpty((String) null) = false 3660 * StringUtils.isNoneEmpty((String[]) null) = true 3661 * StringUtils.isNoneEmpty(null, "foo") = false 3662 * StringUtils.isNoneEmpty("", "bar") = false 3663 * StringUtils.isNoneEmpty("bob", "") = false 3664 * StringUtils.isNoneEmpty(" bob ", null) = false 3665 * StringUtils.isNoneEmpty(new String[] {}) = true 3666 * StringUtils.isNoneEmpty(new String[]{""}) = false 3667 * StringUtils.isNoneEmpty(" ", "bar") = true 3668 * StringUtils.isNoneEmpty("foo", "bar") = true 3669 * </pre> 3670 * 3671 * @param css the CharSequences to check, may be null or empty 3672 * @return {@code true} if none of the CharSequences are empty or null 3673 * @since 3.2 3674 */ 3675 public static boolean isNoneEmpty(final CharSequence... css) { 3676 return !isAnyEmpty(css); 3677 } 3678 3679 /** 3680 * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p> 3681 * 3682 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3683 * 3684 * <pre> 3685 * StringUtils.isNotBlank(null) = false 3686 * StringUtils.isNotBlank("") = false 3687 * StringUtils.isNotBlank(" ") = false 3688 * StringUtils.isNotBlank("bob") = true 3689 * StringUtils.isNotBlank(" bob ") = true 3690 * </pre> 3691 * 3692 * @param cs the CharSequence to check, may be null 3693 * @return {@code true} if the CharSequence is 3694 * not empty and not null and not whitespace only 3695 * @since 2.0 3696 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3697 */ 3698 public static boolean isNotBlank(final CharSequence cs) { 3699 return !isBlank(cs); 3700 } 3701 3702 /** 3703 * <p>Checks if a CharSequence is not empty ("") and not null.</p> 3704 * 3705 * <pre> 3706 * StringUtils.isNotEmpty(null) = false 3707 * StringUtils.isNotEmpty("") = false 3708 * StringUtils.isNotEmpty(" ") = true 3709 * StringUtils.isNotEmpty("bob") = true 3710 * StringUtils.isNotEmpty(" bob ") = true 3711 * </pre> 3712 * 3713 * @param cs the CharSequence to check, may be null 3714 * @return {@code true} if the CharSequence is not empty and not null 3715 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3716 */ 3717 public static boolean isNotEmpty(final CharSequence cs) { 3718 return !isEmpty(cs); 3719 } 3720 3721 /** 3722 * <p>Checks if the CharSequence contains only Unicode digits. 3723 * A decimal point is not a Unicode digit and returns false.</p> 3724 * 3725 * <p>{@code null} will return {@code false}. 3726 * An empty CharSequence (length()=0) will return {@code false}.</p> 3727 * 3728 * <p>Note that the method does not allow for a leading sign, either positive or negative. 3729 * Also, if a String passes the numeric test, it may still generate a NumberFormatException 3730 * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range 3731 * for int or long respectively.</p> 3732 * 3733 * <pre> 3734 * StringUtils.isNumeric(null) = false 3735 * StringUtils.isNumeric("") = false 3736 * StringUtils.isNumeric(" ") = false 3737 * StringUtils.isNumeric("123") = true 3738 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3739 * StringUtils.isNumeric("12 3") = false 3740 * StringUtils.isNumeric("ab2c") = false 3741 * StringUtils.isNumeric("12-3") = false 3742 * StringUtils.isNumeric("12.3") = false 3743 * StringUtils.isNumeric("-123") = false 3744 * StringUtils.isNumeric("+123") = false 3745 * </pre> 3746 * 3747 * @param cs the CharSequence to check, may be null 3748 * @return {@code true} if only contains digits, and is non-null 3749 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3750 * @since 3.0 Changed "" to return false and not true 3751 */ 3752 public static boolean isNumeric(final CharSequence cs) { 3753 if (isEmpty(cs)) { 3754 return false; 3755 } 3756 final int sz = cs.length(); 3757 for (int i = 0; i < sz; i++) { 3758 if (!Character.isDigit(cs.charAt(i))) { 3759 return false; 3760 } 3761 } 3762 return true; 3763 } 3764 3765 /** 3766 * <p>Checks if the CharSequence contains only Unicode digits or space 3767 * ({@code ' '}). 3768 * A decimal point is not a Unicode digit and returns false.</p> 3769 * 3770 * <p>{@code null} will return {@code false}. 3771 * An empty CharSequence (length()=0) will return {@code true}.</p> 3772 * 3773 * <pre> 3774 * StringUtils.isNumericSpace(null) = false 3775 * StringUtils.isNumericSpace("") = true 3776 * StringUtils.isNumericSpace(" ") = true 3777 * StringUtils.isNumericSpace("123") = true 3778 * StringUtils.isNumericSpace("12 3") = true 3779 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3780 * StringUtils.isNumeric("\u0967\u0968 \u0969") = true 3781 * StringUtils.isNumericSpace("ab2c") = false 3782 * StringUtils.isNumericSpace("12-3") = false 3783 * StringUtils.isNumericSpace("12.3") = false 3784 * </pre> 3785 * 3786 * @param cs the CharSequence to check, may be null 3787 * @return {@code true} if only contains digits or space, 3788 * and is non-null 3789 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3790 */ 3791 public static boolean isNumericSpace(final CharSequence cs) { 3792 if (cs == null) { 3793 return false; 3794 } 3795 final int sz = cs.length(); 3796 for (int i = 0; i < sz; i++) { 3797 if (!Character.isDigit(cs.charAt(i)) && cs.charAt(i) != ' ') { 3798 return false; 3799 } 3800 } 3801 return true; 3802 } 3803 3804 /** 3805 * <p>Checks if the CharSequence contains only whitespace.</p> 3806 * 3807 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3808 * 3809 * <p>{@code null} will return {@code false}. 3810 * An empty CharSequence (length()=0) will return {@code true}.</p> 3811 * 3812 * <pre> 3813 * StringUtils.isWhitespace(null) = false 3814 * StringUtils.isWhitespace("") = true 3815 * StringUtils.isWhitespace(" ") = true 3816 * StringUtils.isWhitespace("abc") = false 3817 * StringUtils.isWhitespace("ab2c") = false 3818 * StringUtils.isWhitespace("ab-c") = false 3819 * </pre> 3820 * 3821 * @param cs the CharSequence to check, may be null 3822 * @return {@code true} if only contains whitespace, and is non-null 3823 * @since 2.0 3824 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3825 */ 3826 public static boolean isWhitespace(final CharSequence cs) { 3827 if (cs == null) { 3828 return false; 3829 } 3830 final int sz = cs.length(); 3831 for (int i = 0; i < sz; i++) { 3832 if (!Character.isWhitespace(cs.charAt(i))) { 3833 return false; 3834 } 3835 } 3836 return true; 3837 } 3838 3839 /** 3840 * <p> 3841 * Joins the elements of the provided array into a single String containing the provided list of elements. 3842 * </p> 3843 * 3844 * <p> 3845 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3846 * by empty strings. 3847 * </p> 3848 * 3849 * <pre> 3850 * StringUtils.join(null, *) = null 3851 * StringUtils.join([], *) = "" 3852 * StringUtils.join([null], *) = "" 3853 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3854 * StringUtils.join([1, 2, 3], null) = "123" 3855 * </pre> 3856 * 3857 * @param array 3858 * the array of values to join together, may be null 3859 * @param separator 3860 * the separator character to use 3861 * @return the joined String, {@code null} if null array input 3862 * @since 3.2 3863 */ 3864 public static String join(final byte[] array, final char separator) { 3865 if (array == null) { 3866 return null; 3867 } 3868 return join(array, separator, 0, array.length); 3869 } 3870 3871 /** 3872 * <p> 3873 * Joins the elements of the provided array into a single String containing the provided list of elements. 3874 * </p> 3875 * 3876 * <p> 3877 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3878 * by empty strings. 3879 * </p> 3880 * 3881 * <pre> 3882 * StringUtils.join(null, *) = null 3883 * StringUtils.join([], *) = "" 3884 * StringUtils.join([null], *) = "" 3885 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3886 * StringUtils.join([1, 2, 3], null) = "123" 3887 * </pre> 3888 * 3889 * @param array 3890 * the array of values to join together, may be null 3891 * @param separator 3892 * the separator character to use 3893 * @param startIndex 3894 * the first index to start joining from. It is an error to pass in a start index past the end of the 3895 * array 3896 * @param endIndex 3897 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3898 * the array 3899 * @return the joined String, {@code null} if null array input 3900 * @since 3.2 3901 */ 3902 public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) { 3903 if (array == null) { 3904 return null; 3905 } 3906 final int noOfItems = endIndex - startIndex; 3907 if (noOfItems <= 0) { 3908 return EMPTY; 3909 } 3910 final StringBuilder buf = newStringBuilder(noOfItems); 3911 buf.append(array[startIndex]); 3912 for (int i = startIndex + 1; i < endIndex; i++) { 3913 buf.append(separator); 3914 buf.append(array[i]); 3915 } 3916 return buf.toString(); 3917 } 3918 3919 /** 3920 * <p> 3921 * Joins the elements of the provided array into a single String containing the provided list of elements. 3922 * </p> 3923 * 3924 * <p> 3925 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3926 * by empty strings. 3927 * </p> 3928 * 3929 * <pre> 3930 * StringUtils.join(null, *) = null 3931 * StringUtils.join([], *) = "" 3932 * StringUtils.join([null], *) = "" 3933 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3934 * StringUtils.join([1, 2, 3], null) = "123" 3935 * </pre> 3936 * 3937 * @param array 3938 * the array of values to join together, may be null 3939 * @param separator 3940 * the separator character to use 3941 * @return the joined String, {@code null} if null array input 3942 * @since 3.2 3943 */ 3944 public static String join(final char[] array, final char separator) { 3945 if (array == null) { 3946 return null; 3947 } 3948 return join(array, separator, 0, array.length); 3949 } 3950 3951 /** 3952 * <p> 3953 * Joins the elements of the provided array into a single String containing the provided list of elements. 3954 * </p> 3955 * 3956 * <p> 3957 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3958 * by empty strings. 3959 * </p> 3960 * 3961 * <pre> 3962 * StringUtils.join(null, *) = null 3963 * StringUtils.join([], *) = "" 3964 * StringUtils.join([null], *) = "" 3965 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3966 * StringUtils.join([1, 2, 3], null) = "123" 3967 * </pre> 3968 * 3969 * @param array 3970 * the array of values to join together, may be null 3971 * @param separator 3972 * the separator character to use 3973 * @param startIndex 3974 * the first index to start joining from. It is an error to pass in a start index past the end of the 3975 * array 3976 * @param endIndex 3977 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3978 * the array 3979 * @return the joined String, {@code null} if null array input 3980 * @since 3.2 3981 */ 3982 public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) { 3983 if (array == null) { 3984 return null; 3985 } 3986 final int noOfItems = endIndex - startIndex; 3987 if (noOfItems <= 0) { 3988 return EMPTY; 3989 } 3990 final StringBuilder buf = newStringBuilder(noOfItems); 3991 buf.append(array[startIndex]); 3992 for (int i = startIndex + 1; i < endIndex; i++) { 3993 buf.append(separator); 3994 buf.append(array[i]); 3995 } 3996 return buf.toString(); 3997 } 3998 3999 /** 4000 * <p> 4001 * Joins the elements of the provided array into a single String containing the provided list of elements. 4002 * </p> 4003 * 4004 * <p> 4005 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4006 * by empty strings. 4007 * </p> 4008 * 4009 * <pre> 4010 * StringUtils.join(null, *) = null 4011 * StringUtils.join([], *) = "" 4012 * StringUtils.join([null], *) = "" 4013 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4014 * StringUtils.join([1, 2, 3], null) = "123" 4015 * </pre> 4016 * 4017 * @param array 4018 * the array of values to join together, may be null 4019 * @param separator 4020 * the separator character to use 4021 * @return the joined String, {@code null} if null array input 4022 * @since 3.2 4023 */ 4024 public static String join(final double[] array, final char separator) { 4025 if (array == null) { 4026 return null; 4027 } 4028 return join(array, separator, 0, array.length); 4029 } 4030 4031 /** 4032 * <p> 4033 * Joins the elements of the provided array into a single String containing the provided list of elements. 4034 * </p> 4035 * 4036 * <p> 4037 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4038 * by empty strings. 4039 * </p> 4040 * 4041 * <pre> 4042 * StringUtils.join(null, *) = null 4043 * StringUtils.join([], *) = "" 4044 * StringUtils.join([null], *) = "" 4045 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4046 * StringUtils.join([1, 2, 3], null) = "123" 4047 * </pre> 4048 * 4049 * @param array 4050 * the array of values to join together, may be null 4051 * @param separator 4052 * the separator character to use 4053 * @param startIndex 4054 * the first index to start joining from. It is an error to pass in a start index past the end of the 4055 * array 4056 * @param endIndex 4057 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4058 * the array 4059 * @return the joined String, {@code null} if null array input 4060 * @since 3.2 4061 */ 4062 public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) { 4063 if (array == null) { 4064 return null; 4065 } 4066 final int noOfItems = endIndex - startIndex; 4067 if (noOfItems <= 0) { 4068 return EMPTY; 4069 } 4070 final StringBuilder buf = newStringBuilder(noOfItems); 4071 buf.append(array[startIndex]); 4072 for (int i = startIndex + 1; i < endIndex; i++) { 4073 buf.append(separator); 4074 buf.append(array[i]); 4075 } 4076 return buf.toString(); 4077 } 4078 4079 /** 4080 * <p> 4081 * Joins the elements of the provided array into a single String containing the provided list of elements. 4082 * </p> 4083 * 4084 * <p> 4085 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4086 * by empty strings. 4087 * </p> 4088 * 4089 * <pre> 4090 * StringUtils.join(null, *) = null 4091 * StringUtils.join([], *) = "" 4092 * StringUtils.join([null], *) = "" 4093 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4094 * StringUtils.join([1, 2, 3], null) = "123" 4095 * </pre> 4096 * 4097 * @param array 4098 * the array of values to join together, may be null 4099 * @param separator 4100 * the separator character to use 4101 * @return the joined String, {@code null} if null array input 4102 * @since 3.2 4103 */ 4104 public static String join(final float[] array, final char separator) { 4105 if (array == null) { 4106 return null; 4107 } 4108 return join(array, separator, 0, array.length); 4109 } 4110 4111 /** 4112 * <p> 4113 * Joins the elements of the provided array into a single String containing the provided list of elements. 4114 * </p> 4115 * 4116 * <p> 4117 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4118 * by empty strings. 4119 * </p> 4120 * 4121 * <pre> 4122 * StringUtils.join(null, *) = null 4123 * StringUtils.join([], *) = "" 4124 * StringUtils.join([null], *) = "" 4125 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4126 * StringUtils.join([1, 2, 3], null) = "123" 4127 * </pre> 4128 * 4129 * @param array 4130 * the array of values to join together, may be null 4131 * @param separator 4132 * the separator character to use 4133 * @param startIndex 4134 * the first index to start joining from. It is an error to pass in a start index past the end of the 4135 * array 4136 * @param endIndex 4137 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4138 * the array 4139 * @return the joined String, {@code null} if null array input 4140 * @since 3.2 4141 */ 4142 public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) { 4143 if (array == null) { 4144 return null; 4145 } 4146 final int noOfItems = endIndex - startIndex; 4147 if (noOfItems <= 0) { 4148 return EMPTY; 4149 } 4150 final StringBuilder buf = newStringBuilder(noOfItems); 4151 buf.append(array[startIndex]); 4152 for (int i = startIndex + 1; i < endIndex; i++) { 4153 buf.append(separator); 4154 buf.append(array[i]); 4155 } 4156 return buf.toString(); 4157 } 4158 4159 /** 4160 * <p> 4161 * Joins the elements of the provided array into a single String containing the provided list of elements. 4162 * </p> 4163 * 4164 * <p> 4165 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4166 * by empty strings. 4167 * </p> 4168 * 4169 * <pre> 4170 * StringUtils.join(null, *) = null 4171 * StringUtils.join([], *) = "" 4172 * StringUtils.join([null], *) = "" 4173 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4174 * StringUtils.join([1, 2, 3], null) = "123" 4175 * </pre> 4176 * 4177 * @param array 4178 * the array of values to join together, may be null 4179 * @param separator 4180 * the separator character to use 4181 * @return the joined String, {@code null} if null array input 4182 * @since 3.2 4183 */ 4184 public static String join(final int[] array, final char separator) { 4185 if (array == null) { 4186 return null; 4187 } 4188 return join(array, separator, 0, array.length); 4189 } 4190 4191 /** 4192 * <p> 4193 * Joins the elements of the provided array into a single String containing the provided list of elements. 4194 * </p> 4195 * 4196 * <p> 4197 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4198 * by empty strings. 4199 * </p> 4200 * 4201 * <pre> 4202 * StringUtils.join(null, *) = null 4203 * StringUtils.join([], *) = "" 4204 * StringUtils.join([null], *) = "" 4205 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4206 * StringUtils.join([1, 2, 3], null) = "123" 4207 * </pre> 4208 * 4209 * @param array 4210 * the array of values to join together, may be null 4211 * @param separator 4212 * the separator character to use 4213 * @param startIndex 4214 * the first index to start joining from. It is an error to pass in a start index past the end of the 4215 * array 4216 * @param endIndex 4217 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4218 * the array 4219 * @return the joined String, {@code null} if null array input 4220 * @since 3.2 4221 */ 4222 public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) { 4223 if (array == null) { 4224 return null; 4225 } 4226 final int noOfItems = endIndex - startIndex; 4227 if (noOfItems <= 0) { 4228 return EMPTY; 4229 } 4230 final StringBuilder buf = newStringBuilder(noOfItems); 4231 buf.append(array[startIndex]); 4232 for (int i = startIndex + 1; i < endIndex; i++) { 4233 buf.append(separator); 4234 buf.append(array[i]); 4235 } 4236 return buf.toString(); 4237 } 4238 4239 /** 4240 * <p>Joins the elements of the provided {@code Iterable} into 4241 * a single String containing the provided elements.</p> 4242 * 4243 * <p>No delimiter is added before or after the list. Null objects or empty 4244 * strings within the iteration are represented by empty strings.</p> 4245 * 4246 * <p>See the examples here: {@link #join(Object[],char)}. </p> 4247 * 4248 * @param iterable the {@code Iterable} providing the values to join together, may be null 4249 * @param separator the separator character to use 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 char separator) { 4254 if (iterable == null) { 4255 return null; 4256 } 4257 return join(iterable.iterator(), separator); 4258 } 4259 4260 /** 4261 * <p>Joins the elements of the provided {@code Iterable} into 4262 * a single String containing the provided elements.</p> 4263 * 4264 * <p>No delimiter is added before or after the list. 4265 * A {@code null} separator is the same as an empty String ("").</p> 4266 * 4267 * <p>See the examples here: {@link #join(Object[],String)}. </p> 4268 * 4269 * @param iterable the {@code Iterable} providing the values to join together, may be null 4270 * @param separator the separator character to use, null treated as "" 4271 * @return the joined String, {@code null} if null iterator input 4272 * @since 2.3 4273 */ 4274 public static String join(final Iterable<?> iterable, final String separator) { 4275 if (iterable == null) { 4276 return null; 4277 } 4278 return join(iterable.iterator(), separator); 4279 } 4280 4281 /** 4282 * <p>Joins the elements of the provided {@code Iterator} into 4283 * a single String containing the provided elements.</p> 4284 * 4285 * <p>No delimiter is added before or after the list. Null objects or empty 4286 * strings within the iteration are represented by empty strings.</p> 4287 * 4288 * <p>See the examples here: {@link #join(Object[],char)}. </p> 4289 * 4290 * @param iterator the {@code Iterator} of values to join together, may be null 4291 * @param separator the separator character to use 4292 * @return the joined String, {@code null} if null iterator input 4293 * @since 2.0 4294 */ 4295 public static String join(final Iterator<?> iterator, final char separator) { 4296 4297 // handle null, zero and one elements before building a buffer 4298 if (iterator == null) { 4299 return null; 4300 } 4301 if (!iterator.hasNext()) { 4302 return EMPTY; 4303 } 4304 final Object first = iterator.next(); 4305 if (!iterator.hasNext()) { 4306 return Objects.toString(first, EMPTY); 4307 } 4308 4309 // two or more elements 4310 final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small 4311 if (first != null) { 4312 buf.append(first); 4313 } 4314 4315 while (iterator.hasNext()) { 4316 buf.append(separator); 4317 final Object obj = iterator.next(); 4318 if (obj != null) { 4319 buf.append(obj); 4320 } 4321 } 4322 4323 return buf.toString(); 4324 } 4325 4326 /** 4327 * <p>Joins the elements of the provided {@code Iterator} into 4328 * a single String containing the provided elements.</p> 4329 * 4330 * <p>No delimiter is added before or after the list. 4331 * A {@code null} separator is the same as an empty String ("").</p> 4332 * 4333 * <p>See the examples here: {@link #join(Object[],String)}. </p> 4334 * 4335 * @param iterator the {@code Iterator} of values to join together, may be null 4336 * @param separator the separator character to use, null treated as "" 4337 * @return the joined String, {@code null} if null iterator input 4338 */ 4339 public static String join(final Iterator<?> iterator, final String separator) { 4340 4341 // handle null, zero and one elements before building a buffer 4342 if (iterator == null) { 4343 return null; 4344 } 4345 if (!iterator.hasNext()) { 4346 return EMPTY; 4347 } 4348 final Object first = iterator.next(); 4349 if (!iterator.hasNext()) { 4350 return Objects.toString(first, ""); 4351 } 4352 4353 // two or more elements 4354 final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small 4355 if (first != null) { 4356 buf.append(first); 4357 } 4358 4359 while (iterator.hasNext()) { 4360 if (separator != null) { 4361 buf.append(separator); 4362 } 4363 final Object obj = iterator.next(); 4364 if (obj != null) { 4365 buf.append(obj); 4366 } 4367 } 4368 return buf.toString(); 4369 } 4370 4371 /** 4372 * <p>Joins the elements of the provided {@code List} into a single String 4373 * containing the provided list of elements.</p> 4374 * 4375 * <p>No delimiter is added before or after the list. 4376 * Null objects or empty strings within the array are represented by 4377 * empty strings.</p> 4378 * 4379 * <pre> 4380 * StringUtils.join(null, *) = null 4381 * StringUtils.join([], *) = "" 4382 * StringUtils.join([null], *) = "" 4383 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4384 * StringUtils.join(["a", "b", "c"], null) = "abc" 4385 * StringUtils.join([null, "", "a"], ';') = ";;a" 4386 * </pre> 4387 * 4388 * @param list the {@code List} of values to join together, may be null 4389 * @param separator the separator character to use 4390 * @param startIndex the first index to start joining from. It is 4391 * an error to pass in a start index past the end of the list 4392 * @param endIndex the index to stop joining from (exclusive). It is 4393 * an error to pass in an end index past the end of the list 4394 * @return the joined String, {@code null} if null list input 4395 * @since 3.8 4396 */ 4397 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4398 if (list == null) { 4399 return null; 4400 } 4401 final int noOfItems = endIndex - startIndex; 4402 if (noOfItems <= 0) { 4403 return EMPTY; 4404 } 4405 final List<?> subList = list.subList(startIndex, endIndex); 4406 return join(subList.iterator(), separator); 4407 } 4408 4409 /** 4410 * <p>Joins the elements of the provided {@code List} into a single String 4411 * containing the provided list of elements.</p> 4412 * 4413 * <p>No delimiter is added before or after the list. 4414 * Null objects or empty strings within the array are represented by 4415 * empty strings.</p> 4416 * 4417 * <pre> 4418 * StringUtils.join(null, *) = null 4419 * StringUtils.join([], *) = "" 4420 * StringUtils.join([null], *) = "" 4421 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4422 * StringUtils.join(["a", "b", "c"], null) = "abc" 4423 * StringUtils.join([null, "", "a"], ';') = ";;a" 4424 * </pre> 4425 * 4426 * @param list the {@code List} of values to join together, may be null 4427 * @param separator the separator character to use 4428 * @param startIndex the first index to start joining from. It is 4429 * an error to pass in a start index past the end of the list 4430 * @param endIndex the index to stop joining from (exclusive). It is 4431 * an error to pass in an end index past the end of the list 4432 * @return the joined String, {@code null} if null list input 4433 * @since 3.8 4434 */ 4435 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4436 if (list == null) { 4437 return null; 4438 } 4439 final int noOfItems = endIndex - startIndex; 4440 if (noOfItems <= 0) { 4441 return EMPTY; 4442 } 4443 final List<?> subList = list.subList(startIndex, endIndex); 4444 return join(subList.iterator(), separator); 4445 } 4446 4447 4448 /** 4449 * <p> 4450 * Joins the elements of the provided array into a single String containing the provided list of elements. 4451 * </p> 4452 * 4453 * <p> 4454 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4455 * by empty strings. 4456 * </p> 4457 * 4458 * <pre> 4459 * StringUtils.join(null, *) = null 4460 * StringUtils.join([], *) = "" 4461 * StringUtils.join([null], *) = "" 4462 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4463 * StringUtils.join([1, 2, 3], null) = "123" 4464 * </pre> 4465 * 4466 * @param array 4467 * the array of values to join together, may be null 4468 * @param separator 4469 * the separator character to use 4470 * @return the joined String, {@code null} if null array input 4471 * @since 3.2 4472 */ 4473 public static String join(final long[] array, final char separator) { 4474 if (array == null) { 4475 return null; 4476 } 4477 return join(array, separator, 0, array.length); 4478 } 4479 4480 /** 4481 * <p> 4482 * Joins the elements of the provided array into a single String containing the provided list of elements. 4483 * </p> 4484 * 4485 * <p> 4486 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4487 * by empty strings. 4488 * </p> 4489 * 4490 * <pre> 4491 * StringUtils.join(null, *) = null 4492 * StringUtils.join([], *) = "" 4493 * StringUtils.join([null], *) = "" 4494 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4495 * StringUtils.join([1, 2, 3], null) = "123" 4496 * </pre> 4497 * 4498 * @param array 4499 * the array of values to join together, may be null 4500 * @param separator 4501 * the separator character to use 4502 * @param startIndex 4503 * the first index to start joining from. It is an error to pass in a start index past the end of the 4504 * array 4505 * @param endIndex 4506 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4507 * the array 4508 * @return the joined String, {@code null} if null array input 4509 * @since 3.2 4510 */ 4511 public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) { 4512 if (array == null) { 4513 return null; 4514 } 4515 final int noOfItems = endIndex - startIndex; 4516 if (noOfItems <= 0) { 4517 return EMPTY; 4518 } 4519 final StringBuilder buf = newStringBuilder(noOfItems); 4520 buf.append(array[startIndex]); 4521 for (int i = startIndex + 1; i < endIndex; i++) { 4522 buf.append(separator); 4523 buf.append(array[i]); 4524 } 4525 return buf.toString(); 4526 } 4527 4528 /** 4529 * <p>Joins the elements of the provided array into a single String 4530 * containing the provided list of elements.</p> 4531 * 4532 * <p>No delimiter is added before or after the list. 4533 * Null objects or empty strings within the array are represented by 4534 * empty strings.</p> 4535 * 4536 * <pre> 4537 * StringUtils.join(null, *) = null 4538 * StringUtils.join([], *) = "" 4539 * StringUtils.join([null], *) = "" 4540 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4541 * StringUtils.join(["a", "b", "c"], null) = "abc" 4542 * StringUtils.join([null, "", "a"], ';') = ";;a" 4543 * </pre> 4544 * 4545 * @param array the array of values to join together, may be null 4546 * @param separator the separator character to use 4547 * @return the joined String, {@code null} if null array input 4548 * @since 2.0 4549 */ 4550 public static String join(final Object[] array, final char separator) { 4551 if (array == null) { 4552 return null; 4553 } 4554 return join(array, separator, 0, array.length); 4555 } 4556 4557 /** 4558 * <p>Joins the elements of the provided array into a single String 4559 * containing the provided list of elements.</p> 4560 * 4561 * <p>No delimiter is added before or after the list. 4562 * Null objects or empty strings within the array are represented by 4563 * empty strings.</p> 4564 * 4565 * <pre> 4566 * StringUtils.join(null, *) = null 4567 * StringUtils.join([], *) = "" 4568 * StringUtils.join([null], *) = "" 4569 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4570 * StringUtils.join(["a", "b", "c"], null) = "abc" 4571 * StringUtils.join([null, "", "a"], ';') = ";;a" 4572 * </pre> 4573 * 4574 * @param array the array of values to join together, may be null 4575 * @param separator the separator character to use 4576 * @param startIndex the first index to start joining from. It is 4577 * an error to pass in a start index past the end of the array 4578 * @param endIndex the index to stop joining from (exclusive). It is 4579 * an error to pass in an end index past the end of the array 4580 * @return the joined String, {@code null} if null array input 4581 * @since 2.0 4582 */ 4583 public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) { 4584 if (array == null) { 4585 return null; 4586 } 4587 final int noOfItems = endIndex - startIndex; 4588 if (noOfItems <= 0) { 4589 return EMPTY; 4590 } 4591 final StringBuilder buf = newStringBuilder(noOfItems); 4592 if (array[startIndex] != null) { 4593 buf.append(array[startIndex]); 4594 } 4595 for (int i = startIndex + 1; i < endIndex; i++) { 4596 buf.append(separator); 4597 if (array[i] != null) { 4598 buf.append(array[i]); 4599 } 4600 } 4601 return buf.toString(); 4602 } 4603 4604 /** 4605 * <p>Joins the elements of the provided array into a single String 4606 * containing the provided list of elements.</p> 4607 * 4608 * <p>No delimiter is added before or after the list. 4609 * A {@code null} separator is the same as an empty String (""). 4610 * Null objects or empty strings within the array are represented by 4611 * empty strings.</p> 4612 * 4613 * <pre> 4614 * StringUtils.join(null, *) = null 4615 * StringUtils.join([], *) = "" 4616 * StringUtils.join([null], *) = "" 4617 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 4618 * StringUtils.join(["a", "b", "c"], null) = "abc" 4619 * StringUtils.join(["a", "b", "c"], "") = "abc" 4620 * StringUtils.join([null, "", "a"], ',') = ",,a" 4621 * </pre> 4622 * 4623 * @param array the array of values to join together, may be null 4624 * @param separator the separator character to use, null treated as "" 4625 * @return the joined String, {@code null} if null array input 4626 */ 4627 public static String join(final Object[] array, final String separator) { 4628 if (array == null) { 4629 return null; 4630 } 4631 return join(array, separator, 0, array.length); 4632 } 4633 4634 /** 4635 * <p>Joins the elements of the provided array into a single String 4636 * containing the provided list of elements.</p> 4637 * 4638 * <p>No delimiter is added before or after the list. 4639 * A {@code null} separator is the same as an empty String (""). 4640 * Null objects or empty strings within the array are represented by 4641 * empty strings.</p> 4642 * 4643 * <pre> 4644 * StringUtils.join(null, *, *, *) = null 4645 * StringUtils.join([], *, *, *) = "" 4646 * StringUtils.join([null], *, *, *) = "" 4647 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4648 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4649 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4650 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4651 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4652 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4653 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4654 * </pre> 4655 * 4656 * @param array the array of values to join together, may be null 4657 * @param separator the separator character to use, null treated as "" 4658 * @param startIndex the first index to start joining from. 4659 * @param endIndex the index to stop joining from (exclusive). 4660 * @return the joined String, {@code null} if null array input; or the empty string 4661 * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by 4662 * {@code endIndex - startIndex} 4663 * @throws ArrayIndexOutOfBoundsException ife<br> 4664 * {@code startIndex < 0} or <br> 4665 * {@code startIndex >= array.length()} or <br> 4666 * {@code endIndex < 0} or <br> 4667 * {@code endIndex > array.length()} 4668 */ 4669 public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) { 4670 if (array == null) { 4671 return null; 4672 } 4673 if (separator == null) { 4674 separator = EMPTY; 4675 } 4676 4677 // endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator)) 4678 // (Assuming that all Strings are roughly equally long) 4679 final int noOfItems = endIndex - startIndex; 4680 if (noOfItems <= 0) { 4681 return EMPTY; 4682 } 4683 4684 final StringBuilder buf = newStringBuilder(noOfItems); 4685 4686 if (array[startIndex] != null) { 4687 buf.append(array[startIndex]); 4688 } 4689 4690 for (int i = startIndex + 1; i < endIndex; i++) { 4691 buf.append(separator); 4692 4693 if (array[i] != null) { 4694 buf.append(array[i]); 4695 } 4696 } 4697 return buf.toString(); 4698 } 4699 4700 /** 4701 * <p> 4702 * Joins the elements of the provided array into a single String containing the provided list of elements. 4703 * </p> 4704 * 4705 * <p> 4706 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4707 * by empty strings. 4708 * </p> 4709 * 4710 * <pre> 4711 * StringUtils.join(null, *) = null 4712 * StringUtils.join([], *) = "" 4713 * StringUtils.join([null], *) = "" 4714 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4715 * StringUtils.join([1, 2, 3], null) = "123" 4716 * </pre> 4717 * 4718 * @param array 4719 * the array of values to join together, may be null 4720 * @param separator 4721 * the separator character to use 4722 * @return the joined String, {@code null} if null array input 4723 * @since 3.2 4724 */ 4725 public static String join(final short[] array, final char separator) { 4726 if (array == null) { 4727 return null; 4728 } 4729 return join(array, separator, 0, array.length); 4730 } 4731 4732 /** 4733 * <p> 4734 * Joins the elements of the provided array into a single String containing the provided list of elements. 4735 * </p> 4736 * 4737 * <p> 4738 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4739 * by empty strings. 4740 * </p> 4741 * 4742 * <pre> 4743 * StringUtils.join(null, *) = null 4744 * StringUtils.join([], *) = "" 4745 * StringUtils.join([null], *) = "" 4746 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4747 * StringUtils.join([1, 2, 3], null) = "123" 4748 * </pre> 4749 * 4750 * @param array 4751 * the array of values to join together, may be null 4752 * @param separator 4753 * the separator character to use 4754 * @param startIndex 4755 * the first index to start joining from. It is an error to pass in a start index past the end of the 4756 * array 4757 * @param endIndex 4758 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4759 * the array 4760 * @return the joined String, {@code null} if null array input 4761 * @since 3.2 4762 */ 4763 public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) { 4764 if (array == null) { 4765 return null; 4766 } 4767 final int noOfItems = endIndex - startIndex; 4768 if (noOfItems <= 0) { 4769 return EMPTY; 4770 } 4771 final StringBuilder buf = newStringBuilder(noOfItems); 4772 buf.append(array[startIndex]); 4773 for (int i = startIndex + 1; i < endIndex; i++) { 4774 buf.append(separator); 4775 buf.append(array[i]); 4776 } 4777 return buf.toString(); 4778 } 4779 4780 4781 // Joining 4782 //----------------------------------------------------------------------- 4783 /** 4784 * <p>Joins the elements of the provided array into a single String 4785 * containing the provided list of elements.</p> 4786 * 4787 * <p>No separator is added to the joined String. 4788 * Null objects or empty strings within the array are represented by 4789 * empty strings.</p> 4790 * 4791 * <pre> 4792 * StringUtils.join(null) = null 4793 * StringUtils.join([]) = "" 4794 * StringUtils.join([null]) = "" 4795 * StringUtils.join(["a", "b", "c"]) = "abc" 4796 * StringUtils.join([null, "", "a"]) = "a" 4797 * </pre> 4798 * 4799 * @param <T> the specific type of values to join together 4800 * @param elements the values to join together, may be null 4801 * @return the joined String, {@code null} if null array input 4802 * @since 2.0 4803 * @since 3.0 Changed signature to use varargs 4804 */ 4805 @SafeVarargs 4806 public static <T> String join(final T... elements) { 4807 return join(elements, null); 4808 } 4809 4810 /** 4811 * <p>Joins the elements of the provided varargs into a 4812 * single String containing the provided elements.</p> 4813 * 4814 * <p>No delimiter is added before or after the list. 4815 * {@code null} elements and separator are treated as empty Strings ("").</p> 4816 * 4817 * <pre> 4818 * StringUtils.joinWith(",", {"a", "b"}) = "a,b" 4819 * StringUtils.joinWith(",", {"a", "b",""}) = "a,b," 4820 * StringUtils.joinWith(",", {"a", null, "b"}) = "a,,b" 4821 * StringUtils.joinWith(null, {"a", "b"}) = "ab" 4822 * </pre> 4823 * 4824 * @param separator the separator character to use, null treated as "" 4825 * @param objects the varargs providing the values to join together. {@code null} elements are treated as "" 4826 * @return the joined String. 4827 * @throws java.lang.IllegalArgumentException if a null varargs is provided 4828 * @since 3.5 4829 */ 4830 public static String joinWith(final String separator, final Object... objects) { 4831 if (objects == null) { 4832 throw new IllegalArgumentException("Object varargs must not be null"); 4833 } 4834 4835 final String sanitizedSeparator = defaultString(separator); 4836 4837 final StringBuilder result = new StringBuilder(); 4838 4839 final Iterator<Object> iterator = Arrays.asList(objects).iterator(); 4840 while (iterator.hasNext()) { 4841 final String value = Objects.toString(iterator.next(), ""); 4842 result.append(value); 4843 4844 if (iterator.hasNext()) { 4845 result.append(sanitizedSeparator); 4846 } 4847 } 4848 4849 return result.toString(); 4850 } 4851 4852 /** 4853 * <p>Finds the last index within a CharSequence, handling {@code null}. 4854 * This method uses {@link String#lastIndexOf(String)} if possible.</p> 4855 * 4856 * <p>A {@code null} CharSequence will return {@code -1}.</p> 4857 * 4858 * <pre> 4859 * StringUtils.lastIndexOf(null, *) = -1 4860 * StringUtils.lastIndexOf(*, null) = -1 4861 * StringUtils.lastIndexOf("", "") = 0 4862 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4863 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4864 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4865 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4866 * </pre> 4867 * 4868 * @param seq the CharSequence to check, may be null 4869 * @param searchSeq the CharSequence to find, may be null 4870 * @return the last index of the search String, 4871 * -1 if no match or {@code null} string input 4872 * @since 2.0 4873 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4874 */ 4875 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4876 if (seq == null || searchSeq == null) { 4877 return INDEX_NOT_FOUND; 4878 } 4879 return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length()); 4880 } 4881 4882 /** 4883 * <p>Finds the last index within a CharSequence, handling {@code null}. 4884 * This method uses {@link String#lastIndexOf(String, int)} if possible.</p> 4885 * 4886 * <p>A {@code null} CharSequence will return {@code -1}. 4887 * A negative start position returns {@code -1}. 4888 * An empty ("") search CharSequence always matches unless the start position is negative. 4889 * A start position greater than the string length searches the whole string. 4890 * The search starts at the startPos and works backwards; matches starting after the start 4891 * position are ignored. 4892 * </p> 4893 * 4894 * <pre> 4895 * StringUtils.lastIndexOf(null, *, *) = -1 4896 * StringUtils.lastIndexOf(*, null, *) = -1 4897 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4898 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4899 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4900 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4901 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4902 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4903 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4904 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4905 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4906 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4907 * </pre> 4908 * 4909 * @param seq the CharSequence to check, may be null 4910 * @param searchSeq the CharSequence to find, may be null 4911 * @param startPos the start position, negative treated as zero 4912 * @return the last index of the search CharSequence (always ≤ startPos), 4913 * -1 if no match or {@code null} string input 4914 * @since 2.0 4915 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4916 */ 4917 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4918 if (seq == null || searchSeq == null) { 4919 return INDEX_NOT_FOUND; 4920 } 4921 return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos); 4922 } 4923 4924 // LastIndexOf 4925 //----------------------------------------------------------------------- 4926 /** 4927 * Returns the index within {@code seq} of the last occurrence of 4928 * the specified character. For values of {@code searchChar} in the 4929 * range from 0 to 0xFFFF (inclusive), the index (in Unicode code 4930 * units) returned is the largest value <i>k</i> such that: 4931 * <blockquote><pre> 4932 * this.charAt(<i>k</i>) == searchChar 4933 * </pre></blockquote> 4934 * is true. For other values of {@code searchChar}, it is the 4935 * largest value <i>k</i> such that: 4936 * <blockquote><pre> 4937 * this.codePointAt(<i>k</i>) == searchChar 4938 * </pre></blockquote> 4939 * is true. In either case, if no such character occurs in this 4940 * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4941 * {@code CharSequence} will return {@code -1}. The 4942 * {@code seq} {@code CharSequence} object is searched backwards 4943 * starting at the last character. 4944 * 4945 * <pre> 4946 * StringUtils.lastIndexOf(null, *) = -1 4947 * StringUtils.lastIndexOf("", *) = -1 4948 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4949 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4950 * </pre> 4951 * 4952 * @param seq the {@code CharSequence} to check, may be null 4953 * @param searchChar the character to find 4954 * @return the last index of the search character, 4955 * -1 if no match or {@code null} string input 4956 * @since 2.0 4957 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4958 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String} 4959 */ 4960 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4961 if (isEmpty(seq)) { 4962 return INDEX_NOT_FOUND; 4963 } 4964 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4965 } 4966 4967 /** 4968 * Returns the index within {@code seq} of the last occurrence of 4969 * the specified character, searching backward starting at the 4970 * specified index. For values of {@code searchChar} in the range 4971 * from 0 to 0xFFFF (inclusive), the index returned is the largest 4972 * value <i>k</i> such that: 4973 * <blockquote><pre> 4974 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4975 * </pre></blockquote> 4976 * is true. For other values of {@code searchChar}, it is the 4977 * largest value <i>k</i> such that: 4978 * <blockquote><pre> 4979 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4980 * </pre></blockquote> 4981 * is true. In either case, if no such character occurs in {@code seq} 4982 * at or before position {@code startPos}, then 4983 * {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4984 * {@code CharSequence} will return {@code -1}. A start position greater 4985 * than the string length searches the whole string. 4986 * The search starts at the {@code startPos} and works backwards; 4987 * matches starting after the start position are ignored. 4988 * 4989 * <p>All indices are specified in {@code char} values 4990 * (Unicode code units). 4991 * 4992 * <pre> 4993 * StringUtils.lastIndexOf(null, *, *) = -1 4994 * StringUtils.lastIndexOf("", *, *) = -1 4995 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4996 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4997 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4998 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4999 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 5000 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 5001 * </pre> 5002 * 5003 * @param seq the CharSequence to check, may be null 5004 * @param searchChar the character to find 5005 * @param startPos the start position 5006 * @return the last index of the search character (always ≤ startPos), 5007 * -1 if no match or {@code null} string input 5008 * @since 2.0 5009 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 5010 */ 5011 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 5012 if (isEmpty(seq)) { 5013 return INDEX_NOT_FOUND; 5014 } 5015 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 5016 } 5017 5018 /** 5019 * <p>Find the latest index of any substring in a set of potential substrings.</p> 5020 * 5021 * <p>A {@code null} CharSequence will return {@code -1}. 5022 * A {@code null} search array will return {@code -1}. 5023 * A {@code null} or zero length search array entry will be ignored, 5024 * but a search array containing "" will return the length of {@code str} 5025 * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p> 5026 * 5027 * <pre> 5028 * StringUtils.lastIndexOfAny(null, *) = -1 5029 * StringUtils.lastIndexOfAny(*, null) = -1 5030 * StringUtils.lastIndexOfAny(*, []) = -1 5031 * StringUtils.lastIndexOfAny(*, [null]) = -1 5032 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 5033 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 5034 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5035 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5036 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 5037 * </pre> 5038 * 5039 * @param str the CharSequence to check, may be null 5040 * @param searchStrs the CharSequences to search for, may be null 5041 * @return the last index of any of the CharSequences, -1 if no match 5042 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 5043 */ 5044 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 5045 if (str == null || searchStrs == null) { 5046 return INDEX_NOT_FOUND; 5047 } 5048 int ret = INDEX_NOT_FOUND; 5049 int tmp = 0; 5050 for (final CharSequence search : searchStrs) { 5051 if (search == null) { 5052 continue; 5053 } 5054 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 5055 if (tmp > ret) { 5056 ret = tmp; 5057 } 5058 } 5059 return ret; 5060 } 5061 5062 /** 5063 * <p>Case in-sensitive find of the last index within a CharSequence.</p> 5064 * 5065 * <p>A {@code null} CharSequence will return {@code -1}. 5066 * A negative start position returns {@code -1}. 5067 * An empty ("") search CharSequence always matches unless the start position is negative. 5068 * A start position greater than the string length searches the whole string.</p> 5069 * 5070 * <pre> 5071 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 5072 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 5073 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 5074 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 5075 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 5076 * </pre> 5077 * 5078 * @param str the CharSequence to check, may be null 5079 * @param searchStr the CharSequence to find, may be null 5080 * @return the first index of the search CharSequence, 5081 * -1 if no match or {@code null} string input 5082 * @since 2.5 5083 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 5084 */ 5085 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 5086 if (str == null || searchStr == null) { 5087 return INDEX_NOT_FOUND; 5088 } 5089 return lastIndexOfIgnoreCase(str, searchStr, str.length()); 5090 } 5091 5092 /** 5093 * <p>Case in-sensitive find of the last index within a CharSequence 5094 * from the specified position.</p> 5095 * 5096 * <p>A {@code null} CharSequence will return {@code -1}. 5097 * A negative start position returns {@code -1}. 5098 * An empty ("") search CharSequence always matches unless the start position is negative. 5099 * A start position greater than the string length searches the whole string. 5100 * The search starts at the startPos and works backwards; matches starting after the start 5101 * position are ignored. 5102 * </p> 5103 * 5104 * <pre> 5105 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 5106 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 5107 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 5108 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 5109 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 5110 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 5111 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 5112 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 5113 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 5114 * </pre> 5115 * 5116 * @param str the CharSequence to check, may be null 5117 * @param searchStr the CharSequence to find, may be null 5118 * @param startPos the start position 5119 * @return the last index of the search CharSequence (always ≤ startPos), 5120 * -1 if no match or {@code null} input 5121 * @since 2.5 5122 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 5123 */ 5124 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 5125 if (str == null || searchStr == null) { 5126 return INDEX_NOT_FOUND; 5127 } 5128 if (startPos > str.length() - searchStr.length()) { 5129 startPos = str.length() - searchStr.length(); 5130 } 5131 if (startPos < 0) { 5132 return INDEX_NOT_FOUND; 5133 } 5134 if (searchStr.length() == 0) { 5135 return startPos; 5136 } 5137 5138 for (int i = startPos; i >= 0; i--) { 5139 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 5140 return i; 5141 } 5142 } 5143 return INDEX_NOT_FOUND; 5144 } 5145 5146 /** 5147 * <p>Finds the n-th last index within a String, handling {@code null}. 5148 * This method uses {@link String#lastIndexOf(String)}.</p> 5149 * 5150 * <p>A {@code null} String will return {@code -1}.</p> 5151 * 5152 * <pre> 5153 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5154 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5155 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5156 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5157 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5158 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5159 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5160 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5161 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5162 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5163 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5164 * </pre> 5165 * 5166 * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p> 5167 * 5168 * <pre> 5169 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5170 * </pre> 5171 * 5172 * @param str the CharSequence to check, may be null 5173 * @param searchStr the CharSequence to find, may be null 5174 * @param ordinal the n-th last {@code searchStr} to find 5175 * @return the n-th last index of the search CharSequence, 5176 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5177 * @since 2.5 5178 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5179 */ 5180 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5181 return ordinalIndexOf(str, searchStr, ordinal, true); 5182 } 5183 5184 // Left/Right/Mid 5185 //----------------------------------------------------------------------- 5186 /** 5187 * <p>Gets the leftmost {@code len} characters of a String.</p> 5188 * 5189 * <p>If {@code len} characters are not available, or the 5190 * String is {@code null}, the String will be returned without 5191 * an exception. An empty String is returned if len is negative.</p> 5192 * 5193 * <pre> 5194 * StringUtils.left(null, *) = null 5195 * StringUtils.left(*, -ve) = "" 5196 * StringUtils.left("", *) = "" 5197 * StringUtils.left("abc", 0) = "" 5198 * StringUtils.left("abc", 2) = "ab" 5199 * StringUtils.left("abc", 4) = "abc" 5200 * </pre> 5201 * 5202 * @param str the String to get the leftmost characters from, may be null 5203 * @param len the length of the required String 5204 * @return the leftmost characters, {@code null} if null String input 5205 */ 5206 public static String left(final String str, final int len) { 5207 if (str == null) { 5208 return null; 5209 } 5210 if (len < 0) { 5211 return EMPTY; 5212 } 5213 if (str.length() <= len) { 5214 return str; 5215 } 5216 return str.substring(0, len); 5217 } 5218 5219 /** 5220 * <p>Left pad a String with spaces (' ').</p> 5221 * 5222 * <p>The String is padded to the size of {@code size}.</p> 5223 * 5224 * <pre> 5225 * StringUtils.leftPad(null, *) = null 5226 * StringUtils.leftPad("", 3) = " " 5227 * StringUtils.leftPad("bat", 3) = "bat" 5228 * StringUtils.leftPad("bat", 5) = " bat" 5229 * StringUtils.leftPad("bat", 1) = "bat" 5230 * StringUtils.leftPad("bat", -1) = "bat" 5231 * </pre> 5232 * 5233 * @param str the String to pad out, may be null 5234 * @param size the size to pad to 5235 * @return left padded String or original String if no padding is necessary, 5236 * {@code null} if null String input 5237 */ 5238 public static String leftPad(final String str, final int size) { 5239 return leftPad(str, size, ' '); 5240 } 5241 5242 /** 5243 * <p>Left pad a String with a specified character.</p> 5244 * 5245 * <p>Pad to a size of {@code size}.</p> 5246 * 5247 * <pre> 5248 * StringUtils.leftPad(null, *, *) = null 5249 * StringUtils.leftPad("", 3, 'z') = "zzz" 5250 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5251 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5252 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5253 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5254 * </pre> 5255 * 5256 * @param str the String to pad out, may be null 5257 * @param size the size to pad to 5258 * @param padChar the character to pad with 5259 * @return left padded String or original String if no padding is necessary, 5260 * {@code null} if null String input 5261 * @since 2.0 5262 */ 5263 public static String leftPad(final String str, final int size, final char padChar) { 5264 if (str == null) { 5265 return null; 5266 } 5267 final int pads = size - str.length(); 5268 if (pads <= 0) { 5269 return str; // returns original String when possible 5270 } 5271 if (pads > PAD_LIMIT) { 5272 return leftPad(str, size, String.valueOf(padChar)); 5273 } 5274 return repeat(padChar, pads).concat(str); 5275 } 5276 5277 /** 5278 * <p>Left pad a String with a specified String.</p> 5279 * 5280 * <p>Pad to a size of {@code size}.</p> 5281 * 5282 * <pre> 5283 * StringUtils.leftPad(null, *, *) = null 5284 * StringUtils.leftPad("", 3, "z") = "zzz" 5285 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5286 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5287 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5288 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5289 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5290 * StringUtils.leftPad("bat", 5, null) = " bat" 5291 * StringUtils.leftPad("bat", 5, "") = " bat" 5292 * </pre> 5293 * 5294 * @param str the String to pad out, may be null 5295 * @param size the size to pad to 5296 * @param padStr the String to pad with, null or empty treated as single space 5297 * @return left padded String or original String if no padding is necessary, 5298 * {@code null} if null String input 5299 */ 5300 public static String leftPad(final String str, final int size, String padStr) { 5301 if (str == null) { 5302 return null; 5303 } 5304 if (isEmpty(padStr)) { 5305 padStr = SPACE; 5306 } 5307 final int padLen = padStr.length(); 5308 final int strLen = str.length(); 5309 final int pads = size - strLen; 5310 if (pads <= 0) { 5311 return str; // returns original String when possible 5312 } 5313 if (padLen == 1 && pads <= PAD_LIMIT) { 5314 return leftPad(str, size, padStr.charAt(0)); 5315 } 5316 5317 if (pads == padLen) { 5318 return padStr.concat(str); 5319 } else if (pads < padLen) { 5320 return padStr.substring(0, pads).concat(str); 5321 } else { 5322 final char[] padding = new char[pads]; 5323 final char[] padChars = padStr.toCharArray(); 5324 for (int i = 0; i < pads; i++) { 5325 padding[i] = padChars[i % padLen]; 5326 } 5327 return new String(padding).concat(str); 5328 } 5329 } 5330 5331 /** 5332 * Gets a CharSequence length or {@code 0} if the CharSequence is 5333 * {@code null}. 5334 * 5335 * @param cs 5336 * a CharSequence or {@code null} 5337 * @return CharSequence length or {@code 0} if the CharSequence is 5338 * {@code null}. 5339 * @since 2.4 5340 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5341 */ 5342 public static int length(final CharSequence cs) { 5343 return cs == null ? 0 : cs.length(); 5344 } 5345 5346 /** 5347 * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p> 5348 * 5349 * <p>A {@code null} input String returns {@code null}.</p> 5350 * 5351 * <pre> 5352 * StringUtils.lowerCase(null) = null 5353 * StringUtils.lowerCase("") = "" 5354 * StringUtils.lowerCase("aBc") = "abc" 5355 * </pre> 5356 * 5357 * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, 5358 * the result of this method is affected by the current locale. 5359 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 5360 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 5361 * 5362 * @param str the String to lower case, may be null 5363 * @return the lower cased String, {@code null} if null String input 5364 */ 5365 public static String lowerCase(final String str) { 5366 if (str == null) { 5367 return null; 5368 } 5369 return str.toLowerCase(); 5370 } 5371 5372 /** 5373 * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p> 5374 * 5375 * <p>A {@code null} input String returns {@code null}.</p> 5376 * 5377 * <pre> 5378 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5379 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5380 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5381 * </pre> 5382 * 5383 * @param str the String to lower case, may be null 5384 * @param locale the locale that defines the case transformation rules, must not be null 5385 * @return the lower cased String, {@code null} if null String input 5386 * @since 2.5 5387 */ 5388 public static String lowerCase(final String str, final Locale locale) { 5389 if (str == null) { 5390 return null; 5391 } 5392 return str.toLowerCase(locale); 5393 } 5394 5395 private static int[] matches(final CharSequence first, final CharSequence second) { 5396 CharSequence max, min; 5397 if (first.length() > second.length()) { 5398 max = first; 5399 min = second; 5400 } else { 5401 max = second; 5402 min = first; 5403 } 5404 final int range = Math.max(max.length() / 2 - 1, 0); 5405 final int[] matchIndexes = new int[min.length()]; 5406 Arrays.fill(matchIndexes, -1); 5407 final boolean[] matchFlags = new boolean[max.length()]; 5408 int matches = 0; 5409 for (int mi = 0; mi < min.length(); mi++) { 5410 final char c1 = min.charAt(mi); 5411 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5412 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5413 matchIndexes[mi] = xi; 5414 matchFlags[xi] = true; 5415 matches++; 5416 break; 5417 } 5418 } 5419 } 5420 final char[] ms1 = new char[matches]; 5421 final char[] ms2 = new char[matches]; 5422 for (int i = 0, si = 0; i < min.length(); i++) { 5423 if (matchIndexes[i] != -1) { 5424 ms1[si] = min.charAt(i); 5425 si++; 5426 } 5427 } 5428 for (int i = 0, si = 0; i < max.length(); i++) { 5429 if (matchFlags[i]) { 5430 ms2[si] = max.charAt(i); 5431 si++; 5432 } 5433 } 5434 int transpositions = 0; 5435 for (int mi = 0; mi < ms1.length; mi++) { 5436 if (ms1[mi] != ms2[mi]) { 5437 transpositions++; 5438 } 5439 } 5440 int prefix = 0; 5441 for (int mi = 0; mi < min.length(); mi++) { 5442 if (first.charAt(mi) == second.charAt(mi)) { 5443 prefix++; 5444 } else { 5445 break; 5446 } 5447 } 5448 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5449 } 5450 5451 /** 5452 * <p>Gets {@code len} characters from the middle of a String.</p> 5453 * 5454 * <p>If {@code len} characters are not available, the remainder 5455 * of the String will be returned without an exception. If the 5456 * String is {@code null}, {@code null} will be returned. 5457 * An empty String is returned if len is negative or exceeds the 5458 * length of {@code str}.</p> 5459 * 5460 * <pre> 5461 * StringUtils.mid(null, *, *) = null 5462 * StringUtils.mid(*, *, -ve) = "" 5463 * StringUtils.mid("", 0, *) = "" 5464 * StringUtils.mid("abc", 0, 2) = "ab" 5465 * StringUtils.mid("abc", 0, 4) = "abc" 5466 * StringUtils.mid("abc", 2, 4) = "c" 5467 * StringUtils.mid("abc", 4, 2) = "" 5468 * StringUtils.mid("abc", -2, 2) = "ab" 5469 * </pre> 5470 * 5471 * @param str the String to get the characters from, may be null 5472 * @param pos the position to start from, negative treated as zero 5473 * @param len the length of the required String 5474 * @return the middle characters, {@code null} if null String input 5475 */ 5476 public static String mid(final String str, int pos, final int len) { 5477 if (str == null) { 5478 return null; 5479 } 5480 if (len < 0 || pos > str.length()) { 5481 return EMPTY; 5482 } 5483 if (pos < 0) { 5484 pos = 0; 5485 } 5486 if (str.length() <= pos + len) { 5487 return str.substring(pos); 5488 } 5489 return str.substring(pos, pos + len); 5490 } 5491 5492 private static StringBuilder newStringBuilder(final int noOfItems) { 5493 return new StringBuilder(noOfItems * 16); 5494 } 5495 5496 /** 5497 * <p> 5498 * Similar to <a 5499 * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize 5500 * -space</a> 5501 * </p> 5502 * <p> 5503 * The function returns the argument string with whitespace normalized by using 5504 * {@code {@link #trim(String)}} to remove leading and trailing whitespace 5505 * and then replacing sequences of whitespace characters by a single space. 5506 * </p> 5507 * In XML Whitespace characters are the same as those allowed by the <a 5508 * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+ 5509 * <p> 5510 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 5511 * 5512 * <p>For reference:</p> 5513 * <ul> 5514 * <li>\x0B = vertical tab</li> 5515 * <li>\f = #xC = form feed</li> 5516 * <li>#x20 = space</li> 5517 * <li>#x9 = \t</li> 5518 * <li>#xA = \n</li> 5519 * <li>#xD = \r</li> 5520 * </ul> 5521 * 5522 * <p> 5523 * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also 5524 * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char <= 32) from both 5525 * ends of this String. 5526 * </p> 5527 * 5528 * @see Pattern 5529 * @see #trim(String) 5530 * @see <a 5531 * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize-space</a> 5532 * @param str the source String to normalize whitespaces from, may be null 5533 * @return the modified string with whitespace normalized, {@code null} if null String input 5534 * 5535 * @since 3.0 5536 */ 5537 public static String normalizeSpace(final String str) { 5538 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5539 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5540 if (isEmpty(str)) { 5541 return str; 5542 } 5543 final int size = str.length(); 5544 final char[] newChars = new char[size]; 5545 int count = 0; 5546 int whitespacesCount = 0; 5547 boolean startWhitespaces = true; 5548 for (int i = 0; i < size; i++) { 5549 final char actualChar = str.charAt(i); 5550 final boolean isWhitespace = Character.isWhitespace(actualChar); 5551 if (isWhitespace) { 5552 if (whitespacesCount == 0 && !startWhitespaces) { 5553 newChars[count++] = SPACE.charAt(0); 5554 } 5555 whitespacesCount++; 5556 } else { 5557 startWhitespaces = false; 5558 newChars[count++] = (actualChar == 160 ? 32 : actualChar); 5559 whitespacesCount = 0; 5560 } 5561 } 5562 if (startWhitespaces) { 5563 return EMPTY; 5564 } 5565 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5566 } 5567 5568 /** 5569 * <p>Finds the n-th index within a CharSequence, handling {@code null}. 5570 * This method uses {@link String#indexOf(String)} if possible.</p> 5571 * <p><b>Note:</b> The code starts looking for a match at the start of the target, 5572 * incrementing the starting index by one after each successful match 5573 * (unless {@code searchStr} is an empty string in which case the position 5574 * is never incremented and {@code 0} is returned immediately). 5575 * This means that matches may overlap.</p> 5576 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5577 * 5578 * <pre> 5579 * StringUtils.ordinalIndexOf(null, *, *) = -1 5580 * StringUtils.ordinalIndexOf(*, null, *) = -1 5581 * StringUtils.ordinalIndexOf("", "", *) = 0 5582 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5583 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5584 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5585 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5586 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5587 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5588 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5589 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5590 * </pre> 5591 * 5592 * <p>Matches may overlap:</p> 5593 * <pre> 5594 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5595 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5596 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5597 * 5598 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5599 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5600 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5601 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5602 * </pre> 5603 * 5604 * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p> 5605 * 5606 * <pre> 5607 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5608 * </pre> 5609 * 5610 * @param str the CharSequence to check, may be null 5611 * @param searchStr the CharSequence to find, may be null 5612 * @param ordinal the n-th {@code searchStr} to find 5613 * @return the n-th index of the search CharSequence, 5614 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5615 * @since 2.1 5616 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5617 */ 5618 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5619 return ordinalIndexOf(str, searchStr, ordinal, false); 5620 } 5621 5622 /** 5623 * <p>Finds the n-th index within a String, handling {@code null}. 5624 * This method uses {@link String#indexOf(String)} if possible.</p> 5625 * <p>Note that matches may overlap<p> 5626 * 5627 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5628 * 5629 * @param str the CharSequence to check, may be null 5630 * @param searchStr the CharSequence to find, may be null 5631 * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed. 5632 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf() 5633 * @return the n-th index of the search CharSequence, 5634 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5635 */ 5636 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5637 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5638 if (str == null || searchStr == null || ordinal <= 0) { 5639 return INDEX_NOT_FOUND; 5640 } 5641 if (searchStr.length() == 0) { 5642 return lastIndex ? str.length() : 0; 5643 } 5644 int found = 0; 5645 // set the initial index beyond the end of the string 5646 // this is to allow for the initial index decrement/increment 5647 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5648 do { 5649 if (lastIndex) { 5650 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards thru string 5651 } else { 5652 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5653 } 5654 if (index < 0) { 5655 return index; 5656 } 5657 found++; 5658 } while (found < ordinal); 5659 return index; 5660 } 5661 5662 // Overlay 5663 //----------------------------------------------------------------------- 5664 /** 5665 * <p>Overlays part of a String with another String.</p> 5666 * 5667 * <p>A {@code null} string input returns {@code null}. 5668 * A negative index is treated as zero. 5669 * An index greater than the string length is treated as the string length. 5670 * The start index is always the smaller of the two indices.</p> 5671 * 5672 * <pre> 5673 * StringUtils.overlay(null, *, *, *) = null 5674 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5675 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5676 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5677 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5678 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5679 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5680 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5681 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5682 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5683 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5684 * </pre> 5685 * 5686 * @param str the String to do overlaying in, may be null 5687 * @param overlay the String to overlay, may be null 5688 * @param start the position to start overlaying at 5689 * @param end the position to stop overlaying before 5690 * @return overlayed String, {@code null} if null String input 5691 * @since 2.0 5692 */ 5693 public static String overlay(final String str, String overlay, int start, int end) { 5694 if (str == null) { 5695 return null; 5696 } 5697 if (overlay == null) { 5698 overlay = EMPTY; 5699 } 5700 final int len = str.length(); 5701 if (start < 0) { 5702 start = 0; 5703 } 5704 if (start > len) { 5705 start = len; 5706 } 5707 if (end < 0) { 5708 end = 0; 5709 } 5710 if (end > len) { 5711 end = len; 5712 } 5713 if (start > end) { 5714 final int temp = start; 5715 start = end; 5716 end = temp; 5717 } 5718 return str.substring(0, start) + 5719 overlay + 5720 str.substring(end); 5721 } 5722 5723 /** 5724 * Prepends the prefix to the start of the string if the string does not 5725 * already start with any of the prefixes. 5726 * 5727 * @param str The string. 5728 * @param prefix The prefix to prepend to the start of the string. 5729 * @param ignoreCase Indicates whether the compare should ignore case. 5730 * @param prefixes Additional prefixes that are valid (optional). 5731 * 5732 * @return A new String if prefix was prepended, the same string otherwise. 5733 */ 5734 private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) { 5735 if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) { 5736 return str; 5737 } 5738 if (ArrayUtils.isNotEmpty(prefixes)) { 5739 for (final CharSequence p : prefixes) { 5740 if (startsWith(str, p, ignoreCase)) { 5741 return str; 5742 } 5743 } 5744 } 5745 return prefix.toString() + str; 5746 } 5747 5748 /** 5749 * Prepends the prefix to the start of the string if the string does not 5750 * already start with any of the prefixes. 5751 * 5752 * <pre> 5753 * StringUtils.prependIfMissing(null, null) = null 5754 * StringUtils.prependIfMissing("abc", null) = "abc" 5755 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5756 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5757 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5758 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5759 * </pre> 5760 * <p>With additional prefixes,</p> 5761 * <pre> 5762 * StringUtils.prependIfMissing(null, null, null) = null 5763 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5764 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5765 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5766 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5767 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5768 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5769 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5770 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5771 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5772 * </pre> 5773 * 5774 * @param str The string. 5775 * @param prefix The prefix to prepend to the start of the string. 5776 * @param prefixes Additional prefixes that are valid. 5777 * 5778 * @return A new String if prefix was prepended, the same string otherwise. 5779 * 5780 * @since 3.2 5781 */ 5782 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5783 return prependIfMissing(str, prefix, false, prefixes); 5784 } 5785 5786 /** 5787 * Prepends the prefix to the start of the string if the string does not 5788 * already start, case insensitive, with any of the prefixes. 5789 * 5790 * <pre> 5791 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5792 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5793 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5794 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5795 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5796 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5797 * </pre> 5798 * <p>With additional prefixes,</p> 5799 * <pre> 5800 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5801 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5802 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5803 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5804 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5805 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5806 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5807 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5808 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5809 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5810 * </pre> 5811 * 5812 * @param str The string. 5813 * @param prefix The prefix to prepend to the start of the string. 5814 * @param prefixes Additional prefixes that are valid (optional). 5815 * 5816 * @return A new String if prefix was prepended, the same string otherwise. 5817 * 5818 * @since 3.2 5819 */ 5820 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5821 return prependIfMissing(str, prefix, true, prefixes); 5822 } 5823 5824 /** 5825 * <p>Removes all occurrences of a character from within the source string.</p> 5826 * 5827 * <p>A {@code null} source string will return {@code null}. 5828 * An empty ("") source string will return the empty string.</p> 5829 * 5830 * <pre> 5831 * StringUtils.remove(null, *) = null 5832 * StringUtils.remove("", *) = "" 5833 * StringUtils.remove("queued", 'u') = "qeed" 5834 * StringUtils.remove("queued", 'z') = "queued" 5835 * </pre> 5836 * 5837 * @param str the source String to search, may be null 5838 * @param remove the char to search for and remove, may be null 5839 * @return the substring with the char removed if found, 5840 * {@code null} if null String input 5841 * @since 2.1 5842 */ 5843 public static String remove(final String str, final char remove) { 5844 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5845 return str; 5846 } 5847 final char[] chars = str.toCharArray(); 5848 int pos = 0; 5849 for (int i = 0; i < chars.length; i++) { 5850 if (chars[i] != remove) { 5851 chars[pos++] = chars[i]; 5852 } 5853 } 5854 return new String(chars, 0, pos); 5855 } 5856 5857 /** 5858 * <p>Removes all occurrences of a substring from within the source string.</p> 5859 * 5860 * <p>A {@code null} source string will return {@code null}. 5861 * An empty ("") source string will return the empty string. 5862 * A {@code null} remove string will return the source string. 5863 * An empty ("") remove string will return the source string.</p> 5864 * 5865 * <pre> 5866 * StringUtils.remove(null, *) = null 5867 * StringUtils.remove("", *) = "" 5868 * StringUtils.remove(*, null) = * 5869 * StringUtils.remove(*, "") = * 5870 * StringUtils.remove("queued", "ue") = "qd" 5871 * StringUtils.remove("queued", "zz") = "queued" 5872 * </pre> 5873 * 5874 * @param str the source String to search, may be null 5875 * @param remove the String to search for and remove, may be null 5876 * @return the substring with the string removed if found, 5877 * {@code null} if null String input 5878 * @since 2.1 5879 */ 5880 public static String remove(final String str, final String remove) { 5881 if (isEmpty(str) || isEmpty(remove)) { 5882 return str; 5883 } 5884 return replace(str, remove, EMPTY, -1); 5885 } 5886 5887 /** 5888 * <p>Removes each substring of the text String that matches the given regular expression.</p> 5889 * 5890 * This method is a {@code null} safe equivalent to: 5891 * <ul> 5892 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5893 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5894 * </ul> 5895 * 5896 * <p>A {@code null} reference passed to this method is a no-op.</p> 5897 * 5898 * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option 5899 * is NOT automatically added. 5900 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 5901 * DOTALL is also known as single-line mode in Perl.</p> 5902 * 5903 * <pre> 5904 * StringUtils.removeAll(null, *) = null 5905 * StringUtils.removeAll("any", (String) null) = "any" 5906 * StringUtils.removeAll("any", "") = "any" 5907 * StringUtils.removeAll("any", ".*") = "" 5908 * StringUtils.removeAll("any", ".+") = "" 5909 * StringUtils.removeAll("abc", ".?") = "" 5910 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5911 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5912 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5913 * </pre> 5914 * 5915 * @param text text to remove from, may be null 5916 * @param regex the regular expression to which this string is to be matched 5917 * @return the text with any removes processed, 5918 * {@code null} if null String input 5919 * 5920 * @throws java.util.regex.PatternSyntaxException 5921 * if the regular expression's syntax is invalid 5922 * 5923 * @see #replaceAll(String, String, String) 5924 * @see #removePattern(String, String) 5925 * @see String#replaceAll(String, String) 5926 * @see java.util.regex.Pattern 5927 * @see java.util.regex.Pattern#DOTALL 5928 * @since 3.5 5929 * 5930 * @deprecated Moved to RegExUtils. 5931 */ 5932 @Deprecated 5933 public static String removeAll(final String text, final String regex) { 5934 return RegExUtils.removeAll(text, regex); 5935 } 5936 5937 /** 5938 * <p>Removes a substring only if it is at the end of a source string, 5939 * otherwise returns the source string.</p> 5940 * 5941 * <p>A {@code null} source string will return {@code null}. 5942 * An empty ("") source string will return the empty string. 5943 * A {@code null} search string will return the source string.</p> 5944 * 5945 * <pre> 5946 * StringUtils.removeEnd(null, *) = null 5947 * StringUtils.removeEnd("", *) = "" 5948 * StringUtils.removeEnd(*, null) = * 5949 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5950 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5951 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5952 * StringUtils.removeEnd("abc", "") = "abc" 5953 * </pre> 5954 * 5955 * @param str the source String to search, may be null 5956 * @param remove the String to search for and remove, may be null 5957 * @return the substring with the string removed if found, 5958 * {@code null} if null String input 5959 * @since 2.1 5960 */ 5961 public static String removeEnd(final String str, final String remove) { 5962 if (isEmpty(str) || isEmpty(remove)) { 5963 return str; 5964 } 5965 if (str.endsWith(remove)) { 5966 return str.substring(0, str.length() - remove.length()); 5967 } 5968 return str; 5969 } 5970 5971 /** 5972 * <p>Case insensitive removal of a substring if it is at the end of a source string, 5973 * otherwise returns the source string.</p> 5974 * 5975 * <p>A {@code null} source string will return {@code null}. 5976 * An empty ("") source string will return the empty string. 5977 * A {@code null} search string will return the source string.</p> 5978 * 5979 * <pre> 5980 * StringUtils.removeEndIgnoreCase(null, *) = null 5981 * StringUtils.removeEndIgnoreCase("", *) = "" 5982 * StringUtils.removeEndIgnoreCase(*, null) = * 5983 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5984 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5985 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5986 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5987 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain") 5988 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain") 5989 * </pre> 5990 * 5991 * @param str the source String to search, may be null 5992 * @param remove the String to search for (case insensitive) and remove, may be null 5993 * @return the substring with the string removed if found, 5994 * {@code null} if null String input 5995 * @since 2.4 5996 */ 5997 public static String removeEndIgnoreCase(final String str, final String remove) { 5998 if (isEmpty(str) || isEmpty(remove)) { 5999 return str; 6000 } 6001 if (endsWithIgnoreCase(str, remove)) { 6002 return str.substring(0, str.length() - remove.length()); 6003 } 6004 return str; 6005 } 6006 6007 /** 6008 * <p>Removes the first substring of the text string that matches the given regular expression.</p> 6009 * 6010 * This method is a {@code null} safe equivalent to: 6011 * <ul> 6012 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 6013 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 6014 * </ul> 6015 * 6016 * <p>A {@code null} reference passed to this method is a no-op.</p> 6017 * 6018 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 6019 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6020 * DOTALL is also known as single-line mode in Perl.</p> 6021 * 6022 * <pre> 6023 * StringUtils.removeFirst(null, *) = null 6024 * StringUtils.removeFirst("any", (String) null) = "any" 6025 * StringUtils.removeFirst("any", "") = "any" 6026 * StringUtils.removeFirst("any", ".*") = "" 6027 * StringUtils.removeFirst("any", ".+") = "" 6028 * StringUtils.removeFirst("abc", ".?") = "bc" 6029 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 6030 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 6031 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 6032 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 6033 * </pre> 6034 * 6035 * @param text text to remove from, may be null 6036 * @param regex the regular expression to which this string is to be matched 6037 * @return the text with the first replacement processed, 6038 * {@code null} if null String input 6039 * 6040 * @throws java.util.regex.PatternSyntaxException 6041 * if the regular expression's syntax is invalid 6042 * 6043 * @see #replaceFirst(String, String, String) 6044 * @see String#replaceFirst(String, String) 6045 * @see java.util.regex.Pattern 6046 * @see java.util.regex.Pattern#DOTALL 6047 * @since 3.5 6048 * 6049 * @deprecated Moved to RegExUtils. 6050 */ 6051 @Deprecated 6052 public static String removeFirst(final String text, final String regex) { 6053 return replaceFirst(text, regex, EMPTY); 6054 } 6055 6056 /** 6057 * <p> 6058 * Case insensitive removal of all occurrences of a substring from within 6059 * the source string. 6060 * </p> 6061 * 6062 * <p> 6063 * A {@code null} source string will return {@code null}. An empty ("") 6064 * source string will return the empty string. A {@code null} remove string 6065 * will return the source string. An empty ("") remove string will return 6066 * the source string. 6067 * </p> 6068 * 6069 * <pre> 6070 * StringUtils.removeIgnoreCase(null, *) = null 6071 * StringUtils.removeIgnoreCase("", *) = "" 6072 * StringUtils.removeIgnoreCase(*, null) = * 6073 * StringUtils.removeIgnoreCase(*, "") = * 6074 * StringUtils.removeIgnoreCase("queued", "ue") = "qd" 6075 * StringUtils.removeIgnoreCase("queued", "zz") = "queued" 6076 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd" 6077 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued" 6078 * </pre> 6079 * 6080 * @param str 6081 * the source String to search, may be null 6082 * @param remove 6083 * the String to search for (case insensitive) and remove, may be 6084 * null 6085 * @return the substring with the string removed if found, {@code null} if 6086 * null String input 6087 * @since 3.5 6088 */ 6089 public static String removeIgnoreCase(final String str, final String remove) { 6090 if (isEmpty(str) || isEmpty(remove)) { 6091 return str; 6092 } 6093 return replaceIgnoreCase(str, remove, EMPTY, -1); 6094 } 6095 6096 /** 6097 * <p>Removes each substring of the source String that matches the given regular expression using the DOTALL option. 6098 * </p> 6099 * 6100 * This call is a {@code null} safe equivalent to: 6101 * <ul> 6102 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 6103 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 6104 * </ul> 6105 * 6106 * <p>A {@code null} reference passed to this method is a no-op.</p> 6107 * 6108 * <pre> 6109 * StringUtils.removePattern(null, *) = null 6110 * StringUtils.removePattern("any", (String) null) = "any" 6111 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 6112 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 6113 * </pre> 6114 * 6115 * @param source 6116 * the source string 6117 * @param regex 6118 * the regular expression to which this string is to be matched 6119 * @return The resulting {@code String} 6120 * @see #replacePattern(String, String, String) 6121 * @see String#replaceAll(String, String) 6122 * @see Pattern#DOTALL 6123 * @since 3.2 6124 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6125 * 6126 * @deprecated Moved to RegExUtils. 6127 */ 6128 @Deprecated 6129 public static String removePattern(final String source, final String regex) { 6130 return RegExUtils.removePattern(source, regex); 6131 } 6132 6133 // Remove 6134 //----------------------------------------------------------------------- 6135 /** 6136 * <p>Removes a substring only if it is at the beginning of a source string, 6137 * otherwise returns the source string.</p> 6138 * 6139 * <p>A {@code null} source string will return {@code null}. 6140 * An empty ("") source string will return the empty string. 6141 * A {@code null} search string will return the source string.</p> 6142 * 6143 * <pre> 6144 * StringUtils.removeStart(null, *) = null 6145 * StringUtils.removeStart("", *) = "" 6146 * StringUtils.removeStart(*, null) = * 6147 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 6148 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 6149 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 6150 * StringUtils.removeStart("abc", "") = "abc" 6151 * </pre> 6152 * 6153 * @param str the source String to search, may be null 6154 * @param remove the String to search for and remove, may be null 6155 * @return the substring with the string removed if found, 6156 * {@code null} if null String input 6157 * @since 2.1 6158 */ 6159 public static String removeStart(final String str, final String remove) { 6160 if (isEmpty(str) || isEmpty(remove)) { 6161 return str; 6162 } 6163 if (str.startsWith(remove)) { 6164 return str.substring(remove.length()); 6165 } 6166 return str; 6167 } 6168 6169 /** 6170 * <p>Case insensitive removal of a substring if it is at the beginning of a source string, 6171 * otherwise returns the source string.</p> 6172 * 6173 * <p>A {@code null} source string will return {@code null}. 6174 * An empty ("") source string will return the empty string. 6175 * A {@code null} search string will return the source string.</p> 6176 * 6177 * <pre> 6178 * StringUtils.removeStartIgnoreCase(null, *) = null 6179 * StringUtils.removeStartIgnoreCase("", *) = "" 6180 * StringUtils.removeStartIgnoreCase(*, null) = * 6181 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6182 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6183 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6184 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6185 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6186 * </pre> 6187 * 6188 * @param str the source String to search, may be null 6189 * @param remove the String to search for (case insensitive) and remove, may be null 6190 * @return the substring with the string removed if found, 6191 * {@code null} if null String input 6192 * @since 2.4 6193 */ 6194 public static String removeStartIgnoreCase(final String str, final String remove) { 6195 if (isEmpty(str) || isEmpty(remove)) { 6196 return str; 6197 } 6198 if (startsWithIgnoreCase(str, remove)) { 6199 return str.substring(remove.length()); 6200 } 6201 return str; 6202 } 6203 6204 /** 6205 * <p>Returns padding using the specified delimiter repeated 6206 * to a given length.</p> 6207 * 6208 * <pre> 6209 * StringUtils.repeat('e', 0) = "" 6210 * StringUtils.repeat('e', 3) = "eee" 6211 * StringUtils.repeat('e', -2) = "" 6212 * </pre> 6213 * 6214 * <p>Note: this method does not support padding with 6215 * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6216 * as they require a pair of {@code char}s to be represented. 6217 * If you are needing to support full I18N of your applications 6218 * consider using {@link #repeat(String, int)} instead. 6219 * </p> 6220 * 6221 * @param ch character to repeat 6222 * @param repeat number of times to repeat char, negative treated as zero 6223 * @return String with repeated character 6224 * @see #repeat(String, int) 6225 */ 6226 public static String repeat(final char ch, final int repeat) { 6227 if (repeat <= 0) { 6228 return EMPTY; 6229 } 6230 final char[] buf = new char[repeat]; 6231 for (int i = repeat - 1; i >= 0; i--) { 6232 buf[i] = ch; 6233 } 6234 return new String(buf); 6235 } 6236 6237 // Padding 6238 //----------------------------------------------------------------------- 6239 /** 6240 * <p>Repeat a String {@code repeat} times to form a 6241 * new String.</p> 6242 * 6243 * <pre> 6244 * StringUtils.repeat(null, 2) = null 6245 * StringUtils.repeat("", 0) = "" 6246 * StringUtils.repeat("", 2) = "" 6247 * StringUtils.repeat("a", 3) = "aaa" 6248 * StringUtils.repeat("ab", 2) = "abab" 6249 * StringUtils.repeat("a", -2) = "" 6250 * </pre> 6251 * 6252 * @param str the String to repeat, may be null 6253 * @param repeat number of times to repeat str, negative treated as zero 6254 * @return a new String consisting of the original String repeated, 6255 * {@code null} if null String input 6256 */ 6257 public static String repeat(final String str, final int repeat) { 6258 // Performance tuned for 2.0 (JDK1.4) 6259 6260 if (str == null) { 6261 return null; 6262 } 6263 if (repeat <= 0) { 6264 return EMPTY; 6265 } 6266 final int inputLength = str.length(); 6267 if (repeat == 1 || inputLength == 0) { 6268 return str; 6269 } 6270 if (inputLength == 1 && repeat <= PAD_LIMIT) { 6271 return repeat(str.charAt(0), repeat); 6272 } 6273 6274 final int outputLength = inputLength * repeat; 6275 switch (inputLength) { 6276 case 1 : 6277 return repeat(str.charAt(0), repeat); 6278 case 2 : 6279 final char ch0 = str.charAt(0); 6280 final char ch1 = str.charAt(1); 6281 final char[] output2 = new char[outputLength]; 6282 for (int i = repeat * 2 - 2; i >= 0; i--, i--) { 6283 output2[i] = ch0; 6284 output2[i + 1] = ch1; 6285 } 6286 return new String(output2); 6287 default : 6288 final StringBuilder buf = new StringBuilder(outputLength); 6289 for (int i = 0; i < repeat; i++) { 6290 buf.append(str); 6291 } 6292 return buf.toString(); 6293 } 6294 } 6295 6296 // Conversion 6297 //----------------------------------------------------------------------- 6298 6299 /** 6300 * <p>Repeat a String {@code repeat} times to form a 6301 * new String, with a String separator injected each time. </p> 6302 * 6303 * <pre> 6304 * StringUtils.repeat(null, null, 2) = null 6305 * StringUtils.repeat(null, "x", 2) = null 6306 * StringUtils.repeat("", null, 0) = "" 6307 * StringUtils.repeat("", "", 2) = "" 6308 * StringUtils.repeat("", "x", 3) = "xxx" 6309 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6310 * </pre> 6311 * 6312 * @param str the String to repeat, may be null 6313 * @param separator the String to inject, may be null 6314 * @param repeat number of times to repeat str, negative treated as zero 6315 * @return a new String consisting of the original String repeated, 6316 * {@code null} if null String input 6317 * @since 2.5 6318 */ 6319 public static String repeat(final String str, final String separator, final int repeat) { 6320 if (str == null || separator == null) { 6321 return repeat(str, repeat); 6322 } 6323 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6324 final String result = repeat(str + separator, repeat); 6325 return removeEnd(result, separator); 6326 } 6327 6328 /** 6329 * <p>Replaces all occurrences of a String within another String.</p> 6330 * 6331 * <p>A {@code null} reference passed to this method is a no-op.</p> 6332 * 6333 * <pre> 6334 * StringUtils.replace(null, *, *) = null 6335 * StringUtils.replace("", *, *) = "" 6336 * StringUtils.replace("any", null, *) = "any" 6337 * StringUtils.replace("any", *, null) = "any" 6338 * StringUtils.replace("any", "", *) = "any" 6339 * StringUtils.replace("aba", "a", null) = "aba" 6340 * StringUtils.replace("aba", "a", "") = "b" 6341 * StringUtils.replace("aba", "a", "z") = "zbz" 6342 * </pre> 6343 * 6344 * @see #replace(String text, String searchString, String replacement, int max) 6345 * @param text text to search and replace in, may be null 6346 * @param searchString the String to search for, may be null 6347 * @param replacement the String to replace it with, may be null 6348 * @return the text with any replacements processed, 6349 * {@code null} if null String input 6350 */ 6351 public static String replace(final String text, final String searchString, final String replacement) { 6352 return replace(text, searchString, replacement, -1); 6353 } 6354 6355 /** 6356 * <p>Replaces a String with another String inside a larger String, 6357 * for the first {@code max} values of the search String.</p> 6358 * 6359 * <p>A {@code null} reference passed to this method is a no-op.</p> 6360 * 6361 * <pre> 6362 * StringUtils.replace(null, *, *, *) = null 6363 * StringUtils.replace("", *, *, *) = "" 6364 * StringUtils.replace("any", null, *, *) = "any" 6365 * StringUtils.replace("any", *, null, *) = "any" 6366 * StringUtils.replace("any", "", *, *) = "any" 6367 * StringUtils.replace("any", *, *, 0) = "any" 6368 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6369 * StringUtils.replace("abaa", "a", "", -1) = "b" 6370 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6371 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6372 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6373 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6374 * </pre> 6375 * 6376 * @param text text to search and replace in, may be null 6377 * @param searchString the String to search for, may be null 6378 * @param replacement the String to replace it with, may be null 6379 * @param max maximum number of values to replace, or {@code -1} if no maximum 6380 * @return the text with any replacements processed, 6381 * {@code null} if null String input 6382 */ 6383 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6384 return replace(text, searchString, replacement, max, false); 6385 } 6386 6387 /** 6388 * <p>Replaces a String with another String inside a larger String, 6389 * for the first {@code max} values of the search String, 6390 * case sensitively/insensitively based on {@code ignoreCase} value.</p> 6391 * 6392 * <p>A {@code null} reference passed to this method is a no-op.</p> 6393 * 6394 * <pre> 6395 * StringUtils.replace(null, *, *, *, false) = null 6396 * StringUtils.replace("", *, *, *, false) = "" 6397 * StringUtils.replace("any", null, *, *, false) = "any" 6398 * StringUtils.replace("any", *, null, *, false) = "any" 6399 * StringUtils.replace("any", "", *, *, false) = "any" 6400 * StringUtils.replace("any", *, *, 0, false) = "any" 6401 * StringUtils.replace("abaa", "a", null, -1, false) = "abaa" 6402 * StringUtils.replace("abaa", "a", "", -1, false) = "b" 6403 * StringUtils.replace("abaa", "a", "z", 0, false) = "abaa" 6404 * StringUtils.replace("abaa", "A", "z", 1, false) = "abaa" 6405 * StringUtils.replace("abaa", "A", "z", 1, true) = "zbaa" 6406 * StringUtils.replace("abAa", "a", "z", 2, true) = "zbza" 6407 * StringUtils.replace("abAa", "a", "z", -1, true) = "zbzz" 6408 * </pre> 6409 * 6410 * @param text text to search and replace in, may be null 6411 * @param searchString the String to search for (case insensitive), may be null 6412 * @param replacement the String to replace it with, may be null 6413 * @param max maximum number of values to replace, or {@code -1} if no maximum 6414 * @param ignoreCase if true replace is case insensitive, otherwise case sensitive 6415 * @return the text with any replacements processed, 6416 * {@code null} if null String input 6417 */ 6418 private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) { 6419 if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { 6420 return text; 6421 } 6422 if (ignoreCase) { 6423 searchString = searchString.toLowerCase(); 6424 } 6425 int start = 0; 6426 int end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start); 6427 if (end == INDEX_NOT_FOUND) { 6428 return text; 6429 } 6430 final int replLength = searchString.length(); 6431 int increase = Math.max(replacement.length() - replLength, 0); 6432 increase *= max < 0 ? 16 : Math.min(max, 64); 6433 final StringBuilder buf = new StringBuilder(text.length() + increase); 6434 while (end != INDEX_NOT_FOUND) { 6435 buf.append(text, start, end).append(replacement); 6436 start = end + replLength; 6437 if (--max == 0) { 6438 break; 6439 } 6440 end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start); 6441 } 6442 buf.append(text, start, text.length()); 6443 return buf.toString(); 6444 } 6445 6446 /** 6447 * <p>Replaces each substring of the text String that matches the given regular expression 6448 * with the given replacement.</p> 6449 * 6450 * This method is a {@code null} safe equivalent to: 6451 * <ul> 6452 * <li>{@code text.replaceAll(regex, replacement)}</li> 6453 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 6454 * </ul> 6455 * 6456 * <p>A {@code null} reference passed to this method is a no-op.</p> 6457 * 6458 * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option 6459 * is NOT automatically added. 6460 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6461 * DOTALL is also known as single-line mode in Perl.</p> 6462 * 6463 * <pre> 6464 * StringUtils.replaceAll(null, *, *) = null 6465 * StringUtils.replaceAll("any", (String) null, *) = "any" 6466 * StringUtils.replaceAll("any", *, null) = "any" 6467 * StringUtils.replaceAll("", "", "zzz") = "zzz" 6468 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 6469 * StringUtils.replaceAll("", ".+", "zzz") = "" 6470 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 6471 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 6472 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 6473 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 6474 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6475 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6476 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6477 * </pre> 6478 * 6479 * @param text text to search and replace in, may be null 6480 * @param regex the regular expression to which this string is to be matched 6481 * @param replacement the string to be substituted for each match 6482 * @return the text with any replacements processed, 6483 * {@code null} if null String input 6484 * 6485 * @throws java.util.regex.PatternSyntaxException 6486 * if the regular expression's syntax is invalid 6487 * 6488 * @see #replacePattern(String, String, String) 6489 * @see String#replaceAll(String, String) 6490 * @see java.util.regex.Pattern 6491 * @see java.util.regex.Pattern#DOTALL 6492 * @since 3.5 6493 * 6494 * @deprecated Moved to RegExUtils. 6495 */ 6496 @Deprecated 6497 public static String replaceAll(final String text, final String regex, final String replacement) { 6498 return RegExUtils.replaceAll(text, regex, replacement); 6499 } 6500 6501 // Replace, character based 6502 //----------------------------------------------------------------------- 6503 /** 6504 * <p>Replaces all occurrences of a character in a String with another. 6505 * This is a null-safe version of {@link String#replace(char, char)}.</p> 6506 * 6507 * <p>A {@code null} string input returns {@code null}. 6508 * An empty ("") string input returns an empty string.</p> 6509 * 6510 * <pre> 6511 * StringUtils.replaceChars(null, *, *) = null 6512 * StringUtils.replaceChars("", *, *) = "" 6513 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 6514 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 6515 * </pre> 6516 * 6517 * @param str String to replace characters in, may be null 6518 * @param searchChar the character to search for, may be null 6519 * @param replaceChar the character to replace, may be null 6520 * @return modified String, {@code null} if null string input 6521 * @since 2.0 6522 */ 6523 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 6524 if (str == null) { 6525 return null; 6526 } 6527 return str.replace(searchChar, replaceChar); 6528 } 6529 6530 /** 6531 * <p>Replaces multiple characters in a String in one go. 6532 * This method can also be used to delete characters.</p> 6533 * 6534 * <p>For example:<br> 6535 * {@code replaceChars("hello", "ho", "jy") = jelly}.</p> 6536 * 6537 * <p>A {@code null} string input returns {@code null}. 6538 * An empty ("") string input returns an empty string. 6539 * A null or empty set of search characters returns the input string.</p> 6540 * 6541 * <p>The length of the search characters should normally equal the length 6542 * of the replace characters. 6543 * If the search characters is longer, then the extra search characters 6544 * are deleted. 6545 * If the search characters is shorter, then the extra replace characters 6546 * are ignored.</p> 6547 * 6548 * <pre> 6549 * StringUtils.replaceChars(null, *, *) = null 6550 * StringUtils.replaceChars("", *, *) = "" 6551 * StringUtils.replaceChars("abc", null, *) = "abc" 6552 * StringUtils.replaceChars("abc", "", *) = "abc" 6553 * StringUtils.replaceChars("abc", "b", null) = "ac" 6554 * StringUtils.replaceChars("abc", "b", "") = "ac" 6555 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 6556 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 6557 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 6558 * </pre> 6559 * 6560 * @param str String to replace characters in, may be null 6561 * @param searchChars a set of characters to search for, may be null 6562 * @param replaceChars a set of characters to replace, may be null 6563 * @return modified String, {@code null} if null string input 6564 * @since 2.0 6565 */ 6566 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 6567 if (isEmpty(str) || isEmpty(searchChars)) { 6568 return str; 6569 } 6570 if (replaceChars == null) { 6571 replaceChars = EMPTY; 6572 } 6573 boolean modified = false; 6574 final int replaceCharsLength = replaceChars.length(); 6575 final int strLength = str.length(); 6576 final StringBuilder buf = new StringBuilder(strLength); 6577 for (int i = 0; i < strLength; i++) { 6578 final char ch = str.charAt(i); 6579 final int index = searchChars.indexOf(ch); 6580 if (index >= 0) { 6581 modified = true; 6582 if (index < replaceCharsLength) { 6583 buf.append(replaceChars.charAt(index)); 6584 } 6585 } else { 6586 buf.append(ch); 6587 } 6588 } 6589 if (modified) { 6590 return buf.toString(); 6591 } 6592 return str; 6593 } 6594 6595 /** 6596 * <p> 6597 * Replaces all occurrences of Strings within another String. 6598 * </p> 6599 * 6600 * <p> 6601 * A {@code null} reference passed to this method is a no-op, or if 6602 * any "search string" or "string to replace" is null, that replace will be 6603 * ignored. This will not repeat. For repeating replaces, call the 6604 * overloaded method. 6605 * </p> 6606 * 6607 * <pre> 6608 * StringUtils.replaceEach(null, *, *) = null 6609 * StringUtils.replaceEach("", *, *) = "" 6610 * StringUtils.replaceEach("aba", null, null) = "aba" 6611 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 6612 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 6613 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 6614 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 6615 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 6616 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6617 * (example of how it does not repeat) 6618 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6619 * </pre> 6620 * 6621 * @param text 6622 * text to search and replace in, no-op if null 6623 * @param searchList 6624 * the Strings to search for, no-op if null 6625 * @param replacementList 6626 * the Strings to replace them with, no-op if null 6627 * @return the text with any replacements processed, {@code null} if 6628 * null String input 6629 * @throws IllegalArgumentException 6630 * if the lengths of the arrays are not the same (null is ok, 6631 * and/or size 0) 6632 * @since 2.4 6633 */ 6634 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 6635 return replaceEach(text, searchList, replacementList, false, 0); 6636 } 6637 6638 /** 6639 * <p> 6640 * Replace all occurrences of Strings within another String. 6641 * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and 6642 * {@link #replaceEach(String, String[], String[])} 6643 * </p> 6644 * 6645 * <p> 6646 * A {@code null} reference passed to this method is a no-op, or if 6647 * any "search string" or "string to replace" is null, that replace will be 6648 * ignored. 6649 * </p> 6650 * 6651 * <pre> 6652 * StringUtils.replaceEach(null, *, *, *, *) = null 6653 * StringUtils.replaceEach("", *, *, *, *) = "" 6654 * StringUtils.replaceEach("aba", null, null, *, *) = "aba" 6655 * StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba" 6656 * StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba" 6657 * StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba" 6658 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b" 6659 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba" 6660 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte" 6661 * (example of how it repeats) 6662 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte" 6663 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte" 6664 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException 6665 * </pre> 6666 * 6667 * @param text 6668 * text to search and replace in, no-op if null 6669 * @param searchList 6670 * the Strings to search for, no-op if null 6671 * @param replacementList 6672 * the Strings to replace them with, no-op if null 6673 * @param repeat if true, then replace repeatedly 6674 * until there are no more possible replacements or timeToLive < 0 6675 * @param timeToLive 6676 * if less than 0 then there is a circular reference and endless 6677 * loop 6678 * @return the text with any replacements processed, {@code null} if 6679 * null String input 6680 * @throws IllegalStateException 6681 * if the search is repeating and there is an endless loop due 6682 * to outputs of one being inputs to another 6683 * @throws IllegalArgumentException 6684 * if the lengths of the arrays are not the same (null is ok, 6685 * and/or size 0) 6686 * @since 2.4 6687 */ 6688 private static String replaceEach( 6689 final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) { 6690 6691 // mchyzer Performance note: This creates very few new objects (one major goal) 6692 // let me know if there are performance requests, we can create a harness to measure 6693 6694 // if recursing, this shouldn't be less than 0 6695 if (timeToLive < 0) { 6696 final Set<String> searchSet = new HashSet<>(Arrays.asList(searchList)); 6697 final Set<String> replacementSet = new HashSet<>(Arrays.asList(replacementList)); 6698 searchSet.retainAll(replacementSet); 6699 if (searchSet.size() > 0) { 6700 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6701 "output of one loop is the input of another"); 6702 } 6703 } 6704 6705 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList) || (ArrayUtils.isNotEmpty(searchList) && timeToLive == -1)) { 6706 return text; 6707 } 6708 6709 final int searchLength = searchList.length; 6710 final int replacementLength = replacementList.length; 6711 6712 // make sure lengths are ok, these need to be equal 6713 if (searchLength != replacementLength) { 6714 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6715 + searchLength 6716 + " vs " 6717 + replacementLength); 6718 } 6719 6720 // keep track of which still have matches 6721 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6722 6723 // index on index that the match was found 6724 int textIndex = -1; 6725 int replaceIndex = -1; 6726 int tempIndex = -1; 6727 6728 // index of replace array that will replace the search string found 6729 // NOTE: logic duplicated below START 6730 for (int i = 0; i < searchLength; i++) { 6731 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6732 continue; 6733 } 6734 tempIndex = text.indexOf(searchList[i]); 6735 6736 // see if we need to keep searching for this 6737 if (tempIndex == -1) { 6738 noMoreMatchesForReplIndex[i] = true; 6739 } else { 6740 if (textIndex == -1 || tempIndex < textIndex) { 6741 textIndex = tempIndex; 6742 replaceIndex = i; 6743 } 6744 } 6745 } 6746 // NOTE: logic mostly below END 6747 6748 // no search strings found, we are done 6749 if (textIndex == -1) { 6750 return text; 6751 } 6752 6753 int start = 0; 6754 6755 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6756 int increase = 0; 6757 6758 // count the replacement text elements that are larger than their corresponding text being replaced 6759 for (int i = 0; i < searchList.length; i++) { 6760 if (searchList[i] == null || replacementList[i] == null) { 6761 continue; 6762 } 6763 final int greater = replacementList[i].length() - searchList[i].length(); 6764 if (greater > 0) { 6765 increase += 3 * greater; // assume 3 matches 6766 } 6767 } 6768 // have upper-bound at 20% increase, then let Java take over 6769 increase = Math.min(increase, text.length() / 5); 6770 6771 final StringBuilder buf = new StringBuilder(text.length() + increase); 6772 6773 while (textIndex != -1) { 6774 6775 for (int i = start; i < textIndex; i++) { 6776 buf.append(text.charAt(i)); 6777 } 6778 buf.append(replacementList[replaceIndex]); 6779 6780 start = textIndex + searchList[replaceIndex].length(); 6781 6782 textIndex = -1; 6783 replaceIndex = -1; 6784 tempIndex = -1; 6785 // find the next earliest match 6786 // NOTE: logic mostly duplicated above START 6787 for (int i = 0; i < searchLength; i++) { 6788 if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 6789 searchList[i].isEmpty() || replacementList[i] == null) { 6790 continue; 6791 } 6792 tempIndex = text.indexOf(searchList[i], start); 6793 6794 // see if we need to keep searching for this 6795 if (tempIndex == -1) { 6796 noMoreMatchesForReplIndex[i] = true; 6797 } else { 6798 if (textIndex == -1 || tempIndex < textIndex) { 6799 textIndex = tempIndex; 6800 replaceIndex = i; 6801 } 6802 } 6803 } 6804 // NOTE: logic duplicated above END 6805 6806 } 6807 final int textLength = text.length(); 6808 for (int i = start; i < textLength; i++) { 6809 buf.append(text.charAt(i)); 6810 } 6811 final String result = buf.toString(); 6812 if (!repeat) { 6813 return result; 6814 } 6815 6816 return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); 6817 } 6818 6819 /** 6820 * <p> 6821 * Replaces all occurrences of Strings within another String. 6822 * </p> 6823 * 6824 * <p> 6825 * A {@code null} reference passed to this method is a no-op, or if 6826 * any "search string" or "string to replace" is null, that replace will be 6827 * ignored. 6828 * </p> 6829 * 6830 * <pre> 6831 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6832 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6833 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6834 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6835 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6836 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6837 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6838 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6839 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6840 * (example of how it repeats) 6841 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6842 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException 6843 * </pre> 6844 * 6845 * @param text 6846 * text to search and replace in, no-op if null 6847 * @param searchList 6848 * the Strings to search for, no-op if null 6849 * @param replacementList 6850 * the Strings to replace them with, no-op if null 6851 * @return the text with any replacements processed, {@code null} if 6852 * null String input 6853 * @throws IllegalStateException 6854 * if the search is repeating and there is an endless loop due 6855 * to outputs of one being inputs to another 6856 * @throws IllegalArgumentException 6857 * if the lengths of the arrays are not the same (null is ok, 6858 * and/or size 0) 6859 * @since 2.4 6860 */ 6861 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6862 // timeToLive should be 0 if not used or nothing to replace, else it's 6863 // the length of the replace array 6864 final int timeToLive = searchList == null ? 0 : searchList.length; 6865 return replaceEach(text, searchList, replacementList, true, timeToLive); 6866 } 6867 6868 /** 6869 * <p>Replaces the first substring of the text string that matches the given regular expression 6870 * with the given replacement.</p> 6871 * 6872 * This method is a {@code null} safe equivalent to: 6873 * <ul> 6874 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6875 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6876 * </ul> 6877 * 6878 * <p>A {@code null} reference passed to this method is a no-op.</p> 6879 * 6880 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 6881 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6882 * DOTALL is also known as single-line mode in Perl.</p> 6883 * 6884 * <pre> 6885 * StringUtils.replaceFirst(null, *, *) = null 6886 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6887 * StringUtils.replaceFirst("any", *, null) = "any" 6888 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6889 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6890 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6891 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6892 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6893 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6894 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6895 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6896 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6897 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6898 * </pre> 6899 * 6900 * @param text text to search and replace in, may be null 6901 * @param regex the regular expression to which this string is to be matched 6902 * @param replacement the string to be substituted for the first match 6903 * @return the text with the first replacement processed, 6904 * {@code null} if null String input 6905 * 6906 * @throws java.util.regex.PatternSyntaxException 6907 * if the regular expression's syntax is invalid 6908 * 6909 * @see String#replaceFirst(String, String) 6910 * @see java.util.regex.Pattern 6911 * @see java.util.regex.Pattern#DOTALL 6912 * @since 3.5 6913 * 6914 * @deprecated Moved to RegExUtils. 6915 */ 6916 @Deprecated 6917 public static String replaceFirst(final String text, final String regex, final String replacement) { 6918 return RegExUtils.replaceFirst(text, regex, replacement); 6919 } 6920 6921 /** 6922 * <p>Case insensitively replaces all occurrences of a String within another String.</p> 6923 * 6924 * <p>A {@code null} reference passed to this method is a no-op.</p> 6925 * 6926 * <pre> 6927 * StringUtils.replaceIgnoreCase(null, *, *) = null 6928 * StringUtils.replaceIgnoreCase("", *, *) = "" 6929 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6930 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6931 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6932 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6933 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6934 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6935 * </pre> 6936 * 6937 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6938 * @param text text to search and replace in, may be null 6939 * @param searchString the String to search for (case insensitive), may be null 6940 * @param replacement the String to replace it with, may be null 6941 * @return the text with any replacements processed, 6942 * {@code null} if null String input 6943 * @since 3.5 6944 */ 6945 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6946 return replaceIgnoreCase(text, searchString, replacement, -1); 6947 } 6948 6949 /** 6950 * <p>Case insensitively replaces a String with another String inside a larger String, 6951 * for the first {@code max} values of the search String.</p> 6952 * 6953 * <p>A {@code null} reference passed to this method is a no-op.</p> 6954 * 6955 * <pre> 6956 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6957 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6958 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6959 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6960 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6961 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6962 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6963 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6964 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6965 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6966 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6967 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6968 * </pre> 6969 * 6970 * @param text text to search and replace in, may be null 6971 * @param searchString the String to search for (case insensitive), may be null 6972 * @param replacement the String to replace it with, may be null 6973 * @param max maximum number of values to replace, or {@code -1} if no maximum 6974 * @return the text with any replacements processed, 6975 * {@code null} if null String input 6976 * @since 3.5 6977 */ 6978 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6979 return replace(text, searchString, replacement, max, true); 6980 } 6981 6982 // Replacing 6983 //----------------------------------------------------------------------- 6984 /** 6985 * <p>Replaces a String with another String inside a larger String, once.</p> 6986 * 6987 * <p>A {@code null} reference passed to this method is a no-op.</p> 6988 * 6989 * <pre> 6990 * StringUtils.replaceOnce(null, *, *) = null 6991 * StringUtils.replaceOnce("", *, *) = "" 6992 * StringUtils.replaceOnce("any", null, *) = "any" 6993 * StringUtils.replaceOnce("any", *, null) = "any" 6994 * StringUtils.replaceOnce("any", "", *) = "any" 6995 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6996 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6997 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6998 * </pre> 6999 * 7000 * @see #replace(String text, String searchString, String replacement, int max) 7001 * @param text text to search and replace in, may be null 7002 * @param searchString the String to search for, may be null 7003 * @param replacement the String to replace with, may be null 7004 * @return the text with any replacements processed, 7005 * {@code null} if null String input 7006 */ 7007 public static String replaceOnce(final String text, final String searchString, final String replacement) { 7008 return replace(text, searchString, replacement, 1); 7009 } 7010 7011 /** 7012 * <p>Case insensitively replaces a String with another String inside a larger String, once.</p> 7013 * 7014 * <p>A {@code null} reference passed to this method is a no-op.</p> 7015 * 7016 * <pre> 7017 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 7018 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 7019 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 7020 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 7021 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 7022 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 7023 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 7024 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 7025 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 7026 * </pre> 7027 * 7028 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 7029 * @param text text to search and replace in, may be null 7030 * @param searchString the String to search for (case insensitive), may be null 7031 * @param replacement the String to replace with, may be null 7032 * @return the text with any replacements processed, 7033 * {@code null} if null String input 7034 * @since 3.5 7035 */ 7036 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 7037 return replaceIgnoreCase(text, searchString, replacement, 1); 7038 } 7039 7040 /** 7041 * <p>Replaces each substring of the source String that matches the given regular expression with the given 7042 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.</p> 7043 * 7044 * This call is a {@code null} safe equivalent to: 7045 * <ul> 7046 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 7047 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 7048 * </ul> 7049 * 7050 * <p>A {@code null} reference passed to this method is a no-op.</p> 7051 * 7052 * <pre> 7053 * StringUtils.replacePattern(null, *, *) = null 7054 * StringUtils.replacePattern("any", (String) null, *) = "any" 7055 * StringUtils.replacePattern("any", *, null) = "any" 7056 * StringUtils.replacePattern("", "", "zzz") = "zzz" 7057 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 7058 * StringUtils.replacePattern("", ".+", "zzz") = "" 7059 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 7060 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 7061 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 7062 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 7063 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 7064 * </pre> 7065 * 7066 * @param source 7067 * the source string 7068 * @param regex 7069 * the regular expression to which this string is to be matched 7070 * @param replacement 7071 * the string to be substituted for each match 7072 * @return The resulting {@code String} 7073 * @see #replaceAll(String, String, String) 7074 * @see String#replaceAll(String, String) 7075 * @see Pattern#DOTALL 7076 * @since 3.2 7077 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 7078 * 7079 * @deprecated Moved to RegExUtils. 7080 */ 7081 @Deprecated 7082 public static String replacePattern(final String source, final String regex, final String replacement) { 7083 return RegExUtils.replacePattern(source, regex, replacement); 7084 } 7085 7086 // Reversing 7087 //----------------------------------------------------------------------- 7088 /** 7089 * <p>Reverses a String as per {@link StringBuilder#reverse()}.</p> 7090 * 7091 * <p>A {@code null} String returns {@code null}.</p> 7092 * 7093 * <pre> 7094 * StringUtils.reverse(null) = null 7095 * StringUtils.reverse("") = "" 7096 * StringUtils.reverse("bat") = "tab" 7097 * </pre> 7098 * 7099 * @param str the String to reverse, may be null 7100 * @return the reversed String, {@code null} if null String input 7101 */ 7102 public static String reverse(final String str) { 7103 if (str == null) { 7104 return null; 7105 } 7106 return new StringBuilder(str).reverse().toString(); 7107 } 7108 7109 /** 7110 * <p>Reverses a String that is delimited by a specific character.</p> 7111 * 7112 * <p>The Strings between the delimiters are not reversed. 7113 * Thus java.lang.String becomes String.lang.java (if the delimiter 7114 * is {@code '.'}).</p> 7115 * 7116 * <pre> 7117 * StringUtils.reverseDelimited(null, *) = null 7118 * StringUtils.reverseDelimited("", *) = "" 7119 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 7120 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 7121 * </pre> 7122 * 7123 * @param str the String to reverse, may be null 7124 * @param separatorChar the separator character to use 7125 * @return the reversed String, {@code null} if null String input 7126 * @since 2.0 7127 */ 7128 public static String reverseDelimited(final String str, final char separatorChar) { 7129 if (str == null) { 7130 return null; 7131 } 7132 // could implement manually, but simple way is to reuse other, 7133 // probably slower, methods. 7134 final String[] strs = split(str, separatorChar); 7135 ArrayUtils.reverse(strs); 7136 return join(strs, separatorChar); 7137 } 7138 7139 /** 7140 * <p>Gets the rightmost {@code len} characters of a String.</p> 7141 * 7142 * <p>If {@code len} characters are not available, or the String 7143 * is {@code null}, the String will be returned without an 7144 * an exception. An empty String is returned if len is negative.</p> 7145 * 7146 * <pre> 7147 * StringUtils.right(null, *) = null 7148 * StringUtils.right(*, -ve) = "" 7149 * StringUtils.right("", *) = "" 7150 * StringUtils.right("abc", 0) = "" 7151 * StringUtils.right("abc", 2) = "bc" 7152 * StringUtils.right("abc", 4) = "abc" 7153 * </pre> 7154 * 7155 * @param str the String to get the rightmost characters from, may be null 7156 * @param len the length of the required String 7157 * @return the rightmost characters, {@code null} if null String input 7158 */ 7159 public static String right(final String str, final int len) { 7160 if (str == null) { 7161 return null; 7162 } 7163 if (len < 0) { 7164 return EMPTY; 7165 } 7166 if (str.length() <= len) { 7167 return str; 7168 } 7169 return str.substring(str.length() - len); 7170 } 7171 7172 /** 7173 * <p>Right pad a String with spaces (' ').</p> 7174 * 7175 * <p>The String is padded to the size of {@code size}.</p> 7176 * 7177 * <pre> 7178 * StringUtils.rightPad(null, *) = null 7179 * StringUtils.rightPad("", 3) = " " 7180 * StringUtils.rightPad("bat", 3) = "bat" 7181 * StringUtils.rightPad("bat", 5) = "bat " 7182 * StringUtils.rightPad("bat", 1) = "bat" 7183 * StringUtils.rightPad("bat", -1) = "bat" 7184 * </pre> 7185 * 7186 * @param str the String to pad out, may be null 7187 * @param size the size to pad to 7188 * @return right padded String or original String if no padding is necessary, 7189 * {@code null} if null String input 7190 */ 7191 public static String rightPad(final String str, final int size) { 7192 return rightPad(str, size, ' '); 7193 } 7194 7195 /** 7196 * <p>Right pad a String with a specified character.</p> 7197 * 7198 * <p>The String is padded to the size of {@code size}.</p> 7199 * 7200 * <pre> 7201 * StringUtils.rightPad(null, *, *) = null 7202 * StringUtils.rightPad("", 3, 'z') = "zzz" 7203 * StringUtils.rightPad("bat", 3, 'z') = "bat" 7204 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 7205 * StringUtils.rightPad("bat", 1, 'z') = "bat" 7206 * StringUtils.rightPad("bat", -1, 'z') = "bat" 7207 * </pre> 7208 * 7209 * @param str the String to pad out, may be null 7210 * @param size the size to pad to 7211 * @param padChar the character to pad with 7212 * @return right padded String or original String if no padding is necessary, 7213 * {@code null} if null String input 7214 * @since 2.0 7215 */ 7216 public static String rightPad(final String str, final int size, final char padChar) { 7217 if (str == null) { 7218 return null; 7219 } 7220 final int pads = size - str.length(); 7221 if (pads <= 0) { 7222 return str; // returns original String when possible 7223 } 7224 if (pads > PAD_LIMIT) { 7225 return rightPad(str, size, String.valueOf(padChar)); 7226 } 7227 return str.concat(repeat(padChar, pads)); 7228 } 7229 7230 /** 7231 * <p>Right pad a String with a specified String.</p> 7232 * 7233 * <p>The String is padded to the size of {@code size}.</p> 7234 * 7235 * <pre> 7236 * StringUtils.rightPad(null, *, *) = null 7237 * StringUtils.rightPad("", 3, "z") = "zzz" 7238 * StringUtils.rightPad("bat", 3, "yz") = "bat" 7239 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 7240 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 7241 * StringUtils.rightPad("bat", 1, "yz") = "bat" 7242 * StringUtils.rightPad("bat", -1, "yz") = "bat" 7243 * StringUtils.rightPad("bat", 5, null) = "bat " 7244 * StringUtils.rightPad("bat", 5, "") = "bat " 7245 * </pre> 7246 * 7247 * @param str the String to pad out, may be null 7248 * @param size the size to pad to 7249 * @param padStr the String to pad with, null or empty treated as single space 7250 * @return right padded String or original String if no padding is necessary, 7251 * {@code null} if null String input 7252 */ 7253 public static String rightPad(final String str, final int size, String padStr) { 7254 if (str == null) { 7255 return null; 7256 } 7257 if (isEmpty(padStr)) { 7258 padStr = SPACE; 7259 } 7260 final int padLen = padStr.length(); 7261 final int strLen = str.length(); 7262 final int pads = size - strLen; 7263 if (pads <= 0) { 7264 return str; // returns original String when possible 7265 } 7266 if (padLen == 1 && pads <= PAD_LIMIT) { 7267 return rightPad(str, size, padStr.charAt(0)); 7268 } 7269 7270 if (pads == padLen) { 7271 return str.concat(padStr); 7272 } else if (pads < padLen) { 7273 return str.concat(padStr.substring(0, pads)); 7274 } else { 7275 final char[] padding = new char[pads]; 7276 final char[] padChars = padStr.toCharArray(); 7277 for (int i = 0; i < pads; i++) { 7278 padding[i] = padChars[i % padLen]; 7279 } 7280 return str.concat(new String(padding)); 7281 } 7282 } 7283 7284 // Rotating (circular shift) 7285 //----------------------------------------------------------------------- 7286 /** 7287 * <p>Rotate (circular shift) a String of {@code shift} characters.</p> 7288 * <ul> 7289 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 7290 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 7291 * </ul> 7292 * 7293 * <pre> 7294 * StringUtils.rotate(null, *) = null 7295 * StringUtils.rotate("", *) = "" 7296 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 7297 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 7298 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 7299 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 7300 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 7301 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 7302 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 7303 * </pre> 7304 * 7305 * @param str the String to rotate, may be null 7306 * @param shift number of time to shift (positive : right shift, negative : left shift) 7307 * @return the rotated String, 7308 * or the original String if {@code shift == 0}, 7309 * or {@code null} if null String input 7310 * @since 3.5 7311 */ 7312 public static String rotate(final String str, final int shift) { 7313 if (str == null) { 7314 return null; 7315 } 7316 7317 final int strLen = str.length(); 7318 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7319 return str; 7320 } 7321 7322 final StringBuilder builder = new StringBuilder(strLen); 7323 final int offset = - (shift % strLen); 7324 builder.append(substring(str, offset)); 7325 builder.append(substring(str, 0, offset)); 7326 return builder.toString(); 7327 } 7328 7329 // Splitting 7330 //----------------------------------------------------------------------- 7331 /** 7332 * <p>Splits the provided text into an array, using whitespace as the 7333 * separator. 7334 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 7335 * 7336 * <p>The separator is not included in the returned String array. 7337 * Adjacent separators are treated as one separator. 7338 * For more control over the split use the StrTokenizer class.</p> 7339 * 7340 * <p>A {@code null} input String returns {@code null}.</p> 7341 * 7342 * <pre> 7343 * StringUtils.split(null) = null 7344 * StringUtils.split("") = [] 7345 * StringUtils.split("abc def") = ["abc", "def"] 7346 * StringUtils.split("abc def") = ["abc", "def"] 7347 * StringUtils.split(" abc ") = ["abc"] 7348 * </pre> 7349 * 7350 * @param str the String to parse, may be null 7351 * @return an array of parsed Strings, {@code null} if null String input 7352 */ 7353 public static String[] split(final String str) { 7354 return split(str, null, -1); 7355 } 7356 7357 /** 7358 * <p>Splits the provided text into an array, separator specified. 7359 * This is an alternative to using StringTokenizer.</p> 7360 * 7361 * <p>The separator is not included in the returned String array. 7362 * Adjacent separators are treated as one separator. 7363 * For more control over the split use the StrTokenizer class.</p> 7364 * 7365 * <p>A {@code null} input String returns {@code null}.</p> 7366 * 7367 * <pre> 7368 * StringUtils.split(null, *) = null 7369 * StringUtils.split("", *) = [] 7370 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7371 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7372 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7373 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7374 * </pre> 7375 * 7376 * @param str the String to parse, may be null 7377 * @param separatorChar the character used as the delimiter 7378 * @return an array of parsed Strings, {@code null} if null String input 7379 * @since 2.0 7380 */ 7381 public static String[] split(final String str, final char separatorChar) { 7382 return splitWorker(str, separatorChar, false); 7383 } 7384 7385 /** 7386 * <p>Splits the provided text into an array, separators specified. 7387 * This is an alternative to using StringTokenizer.</p> 7388 * 7389 * <p>The separator is not included in the returned String array. 7390 * Adjacent separators are treated as one separator. 7391 * For more control over the split use the StrTokenizer class.</p> 7392 * 7393 * <p>A {@code null} input String returns {@code null}. 7394 * A {@code null} separatorChars splits on whitespace.</p> 7395 * 7396 * <pre> 7397 * StringUtils.split(null, *) = null 7398 * StringUtils.split("", *) = [] 7399 * StringUtils.split("abc def", null) = ["abc", "def"] 7400 * StringUtils.split("abc def", " ") = ["abc", "def"] 7401 * StringUtils.split("abc def", " ") = ["abc", "def"] 7402 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7403 * </pre> 7404 * 7405 * @param str the String to parse, may be null 7406 * @param separatorChars the characters used as the delimiters, 7407 * {@code null} splits on whitespace 7408 * @return an array of parsed Strings, {@code null} if null String input 7409 */ 7410 public static String[] split(final String str, final String separatorChars) { 7411 return splitWorker(str, separatorChars, -1, false); 7412 } 7413 7414 /** 7415 * <p>Splits the provided text into an array with a maximum length, 7416 * separators specified.</p> 7417 * 7418 * <p>The separator is not included in the returned String array. 7419 * Adjacent separators are treated as one separator.</p> 7420 * 7421 * <p>A {@code null} input String returns {@code null}. 7422 * A {@code null} separatorChars splits on whitespace.</p> 7423 * 7424 * <p>If more than {@code max} delimited substrings are found, the last 7425 * returned string includes all characters after the first {@code max - 1} 7426 * returned strings (including separator characters).</p> 7427 * 7428 * <pre> 7429 * StringUtils.split(null, *, *) = null 7430 * StringUtils.split("", *, *) = [] 7431 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7432 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7433 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7434 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7435 * </pre> 7436 * 7437 * @param str the String to parse, may be null 7438 * @param separatorChars the characters used as the delimiters, 7439 * {@code null} splits on whitespace 7440 * @param max the maximum number of elements to include in the 7441 * array. A zero or negative value implies no limit 7442 * @return an array of parsed Strings, {@code null} if null String input 7443 */ 7444 public static String[] split(final String str, final String separatorChars, final int max) { 7445 return splitWorker(str, separatorChars, max, false); 7446 } 7447 7448 /** 7449 * <p>Splits a String by Character type as returned by 7450 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7451 * characters of the same type are returned as complete tokens. 7452 * <pre> 7453 * StringUtils.splitByCharacterType(null) = null 7454 * StringUtils.splitByCharacterType("") = [] 7455 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7456 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7457 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7458 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7459 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7460 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 7461 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 7462 * </pre> 7463 * @param str the String to split, may be {@code null} 7464 * @return an array of parsed Strings, {@code null} if null String input 7465 * @since 2.4 7466 */ 7467 public static String[] splitByCharacterType(final String str) { 7468 return splitByCharacterType(str, false); 7469 } 7470 7471 /** 7472 * <p>Splits a String by Character type as returned by 7473 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7474 * characters of the same type are returned as complete tokens, with the 7475 * following exception: if {@code camelCase} is {@code true}, 7476 * the character of type {@code Character.UPPERCASE_LETTER}, if any, 7477 * immediately preceding a token of type {@code Character.LOWERCASE_LETTER} 7478 * will belong to the following token rather than to the preceding, if any, 7479 * {@code Character.UPPERCASE_LETTER} token. 7480 * @param str the String to split, may be {@code null} 7481 * @param camelCase whether to use so-called "camel-case" for letter types 7482 * @return an array of parsed Strings, {@code null} if null String input 7483 * @since 2.4 7484 */ 7485 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 7486 if (str == null) { 7487 return null; 7488 } 7489 if (str.isEmpty()) { 7490 return ArrayUtils.EMPTY_STRING_ARRAY; 7491 } 7492 final char[] c = str.toCharArray(); 7493 final List<String> list = new ArrayList<>(); 7494 int tokenStart = 0; 7495 int currentType = Character.getType(c[tokenStart]); 7496 for (int pos = tokenStart + 1; pos < c.length; pos++) { 7497 final int type = Character.getType(c[pos]); 7498 if (type == currentType) { 7499 continue; 7500 } 7501 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 7502 final int newTokenStart = pos - 1; 7503 if (newTokenStart != tokenStart) { 7504 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 7505 tokenStart = newTokenStart; 7506 } 7507 } else { 7508 list.add(new String(c, tokenStart, pos - tokenStart)); 7509 tokenStart = pos; 7510 } 7511 currentType = type; 7512 } 7513 list.add(new String(c, tokenStart, c.length - tokenStart)); 7514 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7515 } 7516 7517 /** 7518 * <p>Splits a String by Character type as returned by 7519 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7520 * characters of the same type are returned as complete tokens, with the 7521 * following exception: the character of type 7522 * {@code Character.UPPERCASE_LETTER}, if any, immediately 7523 * preceding a token of type {@code Character.LOWERCASE_LETTER} 7524 * will belong to the following token rather than to the preceding, if any, 7525 * {@code Character.UPPERCASE_LETTER} token. 7526 * <pre> 7527 * StringUtils.splitByCharacterTypeCamelCase(null) = null 7528 * StringUtils.splitByCharacterTypeCamelCase("") = [] 7529 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7530 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7531 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7532 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 7533 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 7534 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 7535 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 7536 * </pre> 7537 * @param str the String to split, may be {@code null} 7538 * @return an array of parsed Strings, {@code null} if null String input 7539 * @since 2.4 7540 */ 7541 public static String[] splitByCharacterTypeCamelCase(final String str) { 7542 return splitByCharacterType(str, true); 7543 } 7544 7545 /** 7546 * <p>Splits the provided text into an array, separator string specified.</p> 7547 * 7548 * <p>The separator(s) will not be included in the returned String array. 7549 * Adjacent separators are treated as one separator.</p> 7550 * 7551 * <p>A {@code null} input String returns {@code null}. 7552 * A {@code null} separator splits on whitespace.</p> 7553 * 7554 * <pre> 7555 * StringUtils.splitByWholeSeparator(null, *) = null 7556 * StringUtils.splitByWholeSeparator("", *) = [] 7557 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7558 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7559 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7560 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7561 * </pre> 7562 * 7563 * @param str the String to parse, may be null 7564 * @param separator String containing the String to be used as a delimiter, 7565 * {@code null} splits on whitespace 7566 * @return an array of parsed Strings, {@code null} if null String was input 7567 */ 7568 public static String[] splitByWholeSeparator(final String str, final String separator) { 7569 return splitByWholeSeparatorWorker(str, separator, -1, false); 7570 } 7571 7572 /** 7573 * <p>Splits the provided text into an array, separator string specified. 7574 * Returns a maximum of {@code max} substrings.</p> 7575 * 7576 * <p>The separator(s) will not be included in the returned String array. 7577 * Adjacent separators are treated as one separator.</p> 7578 * 7579 * <p>A {@code null} input String returns {@code null}. 7580 * A {@code null} separator splits on whitespace.</p> 7581 * 7582 * <pre> 7583 * StringUtils.splitByWholeSeparator(null, *, *) = null 7584 * StringUtils.splitByWholeSeparator("", *, *) = [] 7585 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7586 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7587 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7588 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7589 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7590 * </pre> 7591 * 7592 * @param str the String to parse, may be null 7593 * @param separator String containing the String to be used as a delimiter, 7594 * {@code null} splits on whitespace 7595 * @param max the maximum number of elements to include in the returned 7596 * array. A zero or negative value implies no limit. 7597 * @return an array of parsed Strings, {@code null} if null String was input 7598 */ 7599 public static String[] splitByWholeSeparator( final String str, final String separator, final int max) { 7600 return splitByWholeSeparatorWorker(str, separator, max, false); 7601 } 7602 7603 /** 7604 * <p>Splits the provided text into an array, separator string specified. </p> 7605 * 7606 * <p>The separator is not included in the returned String array. 7607 * Adjacent separators are treated as separators for empty tokens. 7608 * For more control over the split use the StrTokenizer class.</p> 7609 * 7610 * <p>A {@code null} input String returns {@code null}. 7611 * A {@code null} separator splits on whitespace.</p> 7612 * 7613 * <pre> 7614 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 7615 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 7616 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 7617 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 7618 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7619 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7620 * </pre> 7621 * 7622 * @param str the String to parse, may be null 7623 * @param separator String containing the String to be used as a delimiter, 7624 * {@code null} splits on whitespace 7625 * @return an array of parsed Strings, {@code null} if null String was input 7626 * @since 2.4 7627 */ 7628 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 7629 return splitByWholeSeparatorWorker(str, separator, -1, true); 7630 } 7631 7632 /** 7633 * <p>Splits the provided text into an array, separator string specified. 7634 * Returns a maximum of {@code max} substrings.</p> 7635 * 7636 * <p>The separator is not included in the returned String array. 7637 * Adjacent separators are treated as separators for empty tokens. 7638 * For more control over the split use the StrTokenizer class.</p> 7639 * 7640 * <p>A {@code null} input String returns {@code null}. 7641 * A {@code null} separator splits on whitespace.</p> 7642 * 7643 * <pre> 7644 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 7645 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 7646 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7647 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7648 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7649 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7650 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7651 * </pre> 7652 * 7653 * @param str the String to parse, may be null 7654 * @param separator String containing the String to be used as a delimiter, 7655 * {@code null} splits on whitespace 7656 * @param max the maximum number of elements to include in the returned 7657 * array. A zero or negative value implies no limit. 7658 * @return an array of parsed Strings, {@code null} if null String was input 7659 * @since 2.4 7660 */ 7661 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 7662 return splitByWholeSeparatorWorker(str, separator, max, true); 7663 } 7664 7665 /** 7666 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 7667 * 7668 * @param str the String to parse, may be {@code null} 7669 * @param separator String containing the String to be used as a delimiter, 7670 * {@code null} splits on whitespace 7671 * @param max the maximum number of elements to include in the returned 7672 * array. A zero or negative value implies no limit. 7673 * @param preserveAllTokens if {@code true}, adjacent separators are 7674 * treated as empty token separators; if {@code false}, adjacent 7675 * separators are treated as one separator. 7676 * @return an array of parsed Strings, {@code null} if null String input 7677 * @since 2.4 7678 */ 7679 private static String[] splitByWholeSeparatorWorker( 7680 final String str, final String separator, final int max, final boolean preserveAllTokens) { 7681 if (str == null) { 7682 return null; 7683 } 7684 7685 final int len = str.length(); 7686 7687 if (len == 0) { 7688 return ArrayUtils.EMPTY_STRING_ARRAY; 7689 } 7690 7691 if (separator == null || EMPTY.equals(separator)) { 7692 // Split on whitespace. 7693 return splitWorker(str, null, max, preserveAllTokens); 7694 } 7695 7696 final int separatorLength = separator.length(); 7697 7698 final ArrayList<String> substrings = new ArrayList<>(); 7699 int numberOfSubstrings = 0; 7700 int beg = 0; 7701 int end = 0; 7702 while (end < len) { 7703 end = str.indexOf(separator, beg); 7704 7705 if (end > -1) { 7706 if (end > beg) { 7707 numberOfSubstrings += 1; 7708 7709 if (numberOfSubstrings == max) { 7710 end = len; 7711 substrings.add(str.substring(beg)); 7712 } else { 7713 // The following is OK, because String.substring( beg, end ) excludes 7714 // the character at the position 'end'. 7715 substrings.add(str.substring(beg, end)); 7716 7717 // Set the starting point for the next search. 7718 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 7719 // which is the right calculation: 7720 beg = end + separatorLength; 7721 } 7722 } else { 7723 // We found a consecutive occurrence of the separator, so skip it. 7724 if (preserveAllTokens) { 7725 numberOfSubstrings += 1; 7726 if (numberOfSubstrings == max) { 7727 end = len; 7728 substrings.add(str.substring(beg)); 7729 } else { 7730 substrings.add(EMPTY); 7731 } 7732 } 7733 beg = end + separatorLength; 7734 } 7735 } else { 7736 // String.substring( beg ) goes from 'beg' to the end of the String. 7737 substrings.add(str.substring(beg)); 7738 end = len; 7739 } 7740 } 7741 7742 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7743 } 7744 7745 // ----------------------------------------------------------------------- 7746 /** 7747 * <p>Splits the provided text into an array, using whitespace as the 7748 * separator, preserving all tokens, including empty tokens created by 7749 * adjacent separators. This is an alternative to using StringTokenizer. 7750 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 7751 * 7752 * <p>The separator is not included in the returned String array. 7753 * Adjacent separators are treated as separators for empty tokens. 7754 * For more control over the split use the StrTokenizer class.</p> 7755 * 7756 * <p>A {@code null} input String returns {@code null}.</p> 7757 * 7758 * <pre> 7759 * StringUtils.splitPreserveAllTokens(null) = null 7760 * StringUtils.splitPreserveAllTokens("") = [] 7761 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 7762 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 7763 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 7764 * </pre> 7765 * 7766 * @param str the String to parse, may be {@code null} 7767 * @return an array of parsed Strings, {@code null} if null String input 7768 * @since 2.1 7769 */ 7770 public static String[] splitPreserveAllTokens(final String str) { 7771 return splitWorker(str, null, -1, true); 7772 } 7773 7774 /** 7775 * <p>Splits the provided text into an array, separator specified, 7776 * preserving all tokens, including empty tokens created by adjacent 7777 * separators. This is an alternative to using StringTokenizer.</p> 7778 * 7779 * <p>The separator is not included in the returned String array. 7780 * Adjacent separators are treated as separators for empty tokens. 7781 * For more control over the split use the StrTokenizer class.</p> 7782 * 7783 * <p>A {@code null} input String returns {@code null}.</p> 7784 * 7785 * <pre> 7786 * StringUtils.splitPreserveAllTokens(null, *) = null 7787 * StringUtils.splitPreserveAllTokens("", *) = [] 7788 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 7789 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 7790 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 7791 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 7792 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"] 7793 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""] 7794 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""] 7795 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", a", "b", "c"] 7796 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"] 7797 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""] 7798 * </pre> 7799 * 7800 * @param str the String to parse, may be {@code null} 7801 * @param separatorChar the character used as the delimiter, 7802 * {@code null} splits on whitespace 7803 * @return an array of parsed Strings, {@code null} if null String input 7804 * @since 2.1 7805 */ 7806 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 7807 return splitWorker(str, separatorChar, true); 7808 } 7809 7810 /** 7811 * <p>Splits the provided text into an array, separators specified, 7812 * preserving all tokens, including empty tokens created by adjacent 7813 * separators. This is an alternative to using StringTokenizer.</p> 7814 * 7815 * <p>The separator is not included in the returned String array. 7816 * Adjacent separators are treated as separators for empty tokens. 7817 * For more control over the split use the StrTokenizer class.</p> 7818 * 7819 * <p>A {@code null} input String returns {@code null}. 7820 * A {@code null} separatorChars splits on whitespace.</p> 7821 * 7822 * <pre> 7823 * StringUtils.splitPreserveAllTokens(null, *) = null 7824 * StringUtils.splitPreserveAllTokens("", *) = [] 7825 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 7826 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 7827 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"] 7828 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7829 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 7830 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 7831 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"] 7832 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"] 7833 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"] 7834 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""] 7835 * </pre> 7836 * 7837 * @param str the String to parse, may be {@code null} 7838 * @param separatorChars the characters used as the delimiters, 7839 * {@code null} splits on whitespace 7840 * @return an array of parsed Strings, {@code null} if null String input 7841 * @since 2.1 7842 */ 7843 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 7844 return splitWorker(str, separatorChars, -1, true); 7845 } 7846 7847 /** 7848 * <p>Splits the provided text into an array with a maximum length, 7849 * separators specified, preserving all tokens, including empty tokens 7850 * created by adjacent separators.</p> 7851 * 7852 * <p>The separator is not included in the returned String array. 7853 * Adjacent separators are treated as separators for empty tokens. 7854 * Adjacent separators are treated as one separator.</p> 7855 * 7856 * <p>A {@code null} input String returns {@code null}. 7857 * A {@code null} separatorChars splits on whitespace.</p> 7858 * 7859 * <p>If more than {@code max} delimited substrings are found, the last 7860 * returned string includes all characters after the first {@code max - 1} 7861 * returned strings (including separator characters).</p> 7862 * 7863 * <pre> 7864 * StringUtils.splitPreserveAllTokens(null, *, *) = null 7865 * StringUtils.splitPreserveAllTokens("", *, *) = [] 7866 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7867 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7868 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7869 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7870 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 7871 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 7872 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 7873 * </pre> 7874 * 7875 * @param str the String to parse, may be {@code null} 7876 * @param separatorChars the characters used as the delimiters, 7877 * {@code null} splits on whitespace 7878 * @param max the maximum number of elements to include in the 7879 * array. A zero or negative value implies no limit 7880 * @return an array of parsed Strings, {@code null} if null String input 7881 * @since 2.1 7882 */ 7883 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 7884 return splitWorker(str, separatorChars, max, true); 7885 } 7886 7887 /** 7888 * Performs the logic for the {@code split} and 7889 * {@code splitPreserveAllTokens} methods that do not return a 7890 * maximum array length. 7891 * 7892 * @param str the String to parse, may be {@code null} 7893 * @param separatorChar the separate character 7894 * @param preserveAllTokens if {@code true}, adjacent separators are 7895 * treated as empty token separators; if {@code false}, adjacent 7896 * separators are treated as one separator. 7897 * @return an array of parsed Strings, {@code null} if null String input 7898 */ 7899 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 7900 // Performance tuned for 2.0 (JDK1.4) 7901 7902 if (str == null) { 7903 return null; 7904 } 7905 final int len = str.length(); 7906 if (len == 0) { 7907 return ArrayUtils.EMPTY_STRING_ARRAY; 7908 } 7909 final List<String> list = new ArrayList<>(); 7910 int i = 0, start = 0; 7911 boolean match = false; 7912 boolean lastMatch = false; 7913 while (i < len) { 7914 if (str.charAt(i) == separatorChar) { 7915 if (match || preserveAllTokens) { 7916 list.add(str.substring(start, i)); 7917 match = false; 7918 lastMatch = true; 7919 } 7920 start = ++i; 7921 continue; 7922 } 7923 lastMatch = false; 7924 match = true; 7925 i++; 7926 } 7927 if (match || preserveAllTokens && lastMatch) { 7928 list.add(str.substring(start, i)); 7929 } 7930 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7931 } 7932 7933 /** 7934 * Performs the logic for the {@code split} and 7935 * {@code splitPreserveAllTokens} methods that return a maximum array 7936 * length. 7937 * 7938 * @param str the String to parse, may be {@code null} 7939 * @param separatorChars the separate character 7940 * @param max the maximum number of elements to include in the 7941 * array. A zero or negative value implies no limit. 7942 * @param preserveAllTokens if {@code true}, adjacent separators are 7943 * treated as empty token separators; if {@code false}, adjacent 7944 * separators are treated as one separator. 7945 * @return an array of parsed Strings, {@code null} if null String input 7946 */ 7947 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 7948 // Performance tuned for 2.0 (JDK1.4) 7949 // Direct code is quicker than StringTokenizer. 7950 // Also, StringTokenizer uses isSpace() not isWhitespace() 7951 7952 if (str == null) { 7953 return null; 7954 } 7955 final int len = str.length(); 7956 if (len == 0) { 7957 return ArrayUtils.EMPTY_STRING_ARRAY; 7958 } 7959 final List<String> list = new ArrayList<>(); 7960 int sizePlus1 = 1; 7961 int i = 0, start = 0; 7962 boolean match = false; 7963 boolean lastMatch = false; 7964 if (separatorChars == null) { 7965 // Null separator means use whitespace 7966 while (i < len) { 7967 if (Character.isWhitespace(str.charAt(i))) { 7968 if (match || preserveAllTokens) { 7969 lastMatch = true; 7970 if (sizePlus1++ == max) { 7971 i = len; 7972 lastMatch = false; 7973 } 7974 list.add(str.substring(start, i)); 7975 match = false; 7976 } 7977 start = ++i; 7978 continue; 7979 } 7980 lastMatch = false; 7981 match = true; 7982 i++; 7983 } 7984 } else if (separatorChars.length() == 1) { 7985 // Optimise 1 character case 7986 final char sep = separatorChars.charAt(0); 7987 while (i < len) { 7988 if (str.charAt(i) == sep) { 7989 if (match || preserveAllTokens) { 7990 lastMatch = true; 7991 if (sizePlus1++ == max) { 7992 i = len; 7993 lastMatch = false; 7994 } 7995 list.add(str.substring(start, i)); 7996 match = false; 7997 } 7998 start = ++i; 7999 continue; 8000 } 8001 lastMatch = false; 8002 match = true; 8003 i++; 8004 } 8005 } else { 8006 // standard case 8007 while (i < len) { 8008 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 8009 if (match || preserveAllTokens) { 8010 lastMatch = true; 8011 if (sizePlus1++ == max) { 8012 i = len; 8013 lastMatch = false; 8014 } 8015 list.add(str.substring(start, i)); 8016 match = false; 8017 } 8018 start = ++i; 8019 continue; 8020 } 8021 lastMatch = false; 8022 match = true; 8023 i++; 8024 } 8025 } 8026 if (match || preserveAllTokens && lastMatch) { 8027 list.add(str.substring(start, i)); 8028 } 8029 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8030 } 8031 8032 /** 8033 * <p>Check if a CharSequence starts with a specified prefix.</p> 8034 * 8035 * <p>{@code null}s are handled without exceptions. Two {@code null} 8036 * references are considered to be equal. The comparison is case sensitive.</p> 8037 * 8038 * <pre> 8039 * StringUtils.startsWith(null, null) = true 8040 * StringUtils.startsWith(null, "abc") = false 8041 * StringUtils.startsWith("abcdef", null) = false 8042 * StringUtils.startsWith("abcdef", "abc") = true 8043 * StringUtils.startsWith("ABCDEF", "abc") = false 8044 * </pre> 8045 * 8046 * @see java.lang.String#startsWith(String) 8047 * @param str the CharSequence to check, may be null 8048 * @param prefix the prefix to find, may be null 8049 * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or 8050 * both {@code null} 8051 * @since 2.4 8052 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 8053 */ 8054 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 8055 return startsWith(str, prefix, false); 8056 } 8057 8058 /** 8059 * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p> 8060 * 8061 * @see java.lang.String#startsWith(String) 8062 * @param str the CharSequence to check, may be null 8063 * @param prefix the prefix to find, may be null 8064 * @param ignoreCase indicates whether the compare should ignore case 8065 * (case insensitive) or not. 8066 * @return {@code true} if the CharSequence starts with the prefix or 8067 * both {@code null} 8068 */ 8069 private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) { 8070 if (str == null || prefix == null) { 8071 return str == prefix; 8072 } 8073 if (prefix.length() > str.length()) { 8074 return false; 8075 } 8076 return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length()); 8077 } 8078 8079 /** 8080 * <p>Check if a CharSequence starts with any of the provided case-sensitive prefixes.</p> 8081 * 8082 * <pre> 8083 * StringUtils.startsWithAny(null, null) = false 8084 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 8085 * StringUtils.startsWithAny("abcxyz", null) = false 8086 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true 8087 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 8088 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 8089 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false 8090 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false 8091 * </pre> 8092 * 8093 * @param sequence the CharSequence to check, may be null 8094 * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null} 8095 * @see StringUtils#startsWith(CharSequence, CharSequence) 8096 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or 8097 * the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}. 8098 * @since 2.5 8099 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 8100 */ 8101 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 8102 if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { 8103 return false; 8104 } 8105 for (final CharSequence searchString : searchStrings) { 8106 if (startsWith(sequence, searchString)) { 8107 return true; 8108 } 8109 } 8110 return false; 8111 } 8112 8113 /** 8114 * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p> 8115 * 8116 * <p>{@code null}s are handled without exceptions. Two {@code null} 8117 * references are considered to be equal. The comparison is case insensitive.</p> 8118 * 8119 * <pre> 8120 * StringUtils.startsWithIgnoreCase(null, null) = true 8121 * StringUtils.startsWithIgnoreCase(null, "abc") = false 8122 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 8123 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 8124 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 8125 * </pre> 8126 * 8127 * @see java.lang.String#startsWith(String) 8128 * @param str the CharSequence to check, may be null 8129 * @param prefix the prefix to find, may be null 8130 * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or 8131 * both {@code null} 8132 * @since 2.4 8133 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 8134 */ 8135 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 8136 return startsWith(str, prefix, true); 8137 } 8138 8139 // Stripping 8140 //----------------------------------------------------------------------- 8141 /** 8142 * <p>Strips whitespace from the start and end of a String.</p> 8143 * 8144 * <p>This is similar to {@link #trim(String)} but removes whitespace. 8145 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8146 * 8147 * <p>A {@code null} input String returns {@code null}.</p> 8148 * 8149 * <pre> 8150 * StringUtils.strip(null) = null 8151 * StringUtils.strip("") = "" 8152 * StringUtils.strip(" ") = "" 8153 * StringUtils.strip("abc") = "abc" 8154 * StringUtils.strip(" abc") = "abc" 8155 * StringUtils.strip("abc ") = "abc" 8156 * StringUtils.strip(" abc ") = "abc" 8157 * StringUtils.strip(" ab c ") = "ab c" 8158 * </pre> 8159 * 8160 * @param str the String to remove whitespace from, may be null 8161 * @return the stripped String, {@code null} if null String input 8162 */ 8163 public static String strip(final String str) { 8164 return strip(str, null); 8165 } 8166 8167 /** 8168 * <p>Strips any of a set of characters from the start and end of a String. 8169 * This is similar to {@link String#trim()} but allows the characters 8170 * to be stripped to be controlled.</p> 8171 * 8172 * <p>A {@code null} input String returns {@code null}. 8173 * An empty string ("") input returns the empty string.</p> 8174 * 8175 * <p>If the stripChars String is {@code null}, whitespace is 8176 * stripped as defined by {@link Character#isWhitespace(char)}. 8177 * Alternatively use {@link #strip(String)}.</p> 8178 * 8179 * <pre> 8180 * StringUtils.strip(null, *) = null 8181 * StringUtils.strip("", *) = "" 8182 * StringUtils.strip("abc", null) = "abc" 8183 * StringUtils.strip(" abc", null) = "abc" 8184 * StringUtils.strip("abc ", null) = "abc" 8185 * StringUtils.strip(" abc ", null) = "abc" 8186 * StringUtils.strip(" abcyx", "xyz") = " abc" 8187 * </pre> 8188 * 8189 * @param str the String to remove characters from, may be null 8190 * @param stripChars the characters to remove, null treated as whitespace 8191 * @return the stripped String, {@code null} if null String input 8192 */ 8193 public static String strip(String str, final String stripChars) { 8194 if (isEmpty(str)) { 8195 return str; 8196 } 8197 str = stripStart(str, stripChars); 8198 return stripEnd(str, stripChars); 8199 } 8200 8201 /** 8202 * <p>Removes diacritics (~= accents) from a string. The case will not be altered.</p> 8203 * <p>For instance, 'à' will be replaced by 'a'.</p> 8204 * <p>Note that ligatures will be left as is.</p> 8205 * 8206 * <pre> 8207 * StringUtils.stripAccents(null) = null 8208 * StringUtils.stripAccents("") = "" 8209 * StringUtils.stripAccents("control") = "control" 8210 * StringUtils.stripAccents("éclair") = "eclair" 8211 * </pre> 8212 * 8213 * @param input String to be stripped 8214 * @return input text with diacritics removed 8215 * 8216 * @since 3.0 8217 */ 8218 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907). 8219 public static String stripAccents(final String input) { 8220 if (input == null) { 8221 return null; 8222 } 8223 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD)); 8224 convertRemainingAccentCharacters(decomposed); 8225 // Note that this doesn't correctly remove ligatures... 8226 return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY); 8227 } 8228 8229 // StripAll 8230 //----------------------------------------------------------------------- 8231 /** 8232 * <p>Strips whitespace from the start and end of every String in an array. 8233 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8234 * 8235 * <p>A new array is returned each time, except for length zero. 8236 * A {@code null} array will return {@code null}. 8237 * An empty array will return itself. 8238 * A {@code null} array entry will be ignored.</p> 8239 * 8240 * <pre> 8241 * StringUtils.stripAll(null) = null 8242 * StringUtils.stripAll([]) = [] 8243 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 8244 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 8245 * </pre> 8246 * 8247 * @param strs the array to remove whitespace from, may be null 8248 * @return the stripped Strings, {@code null} if null array input 8249 */ 8250 public static String[] stripAll(final String... strs) { 8251 return stripAll(strs, null); 8252 } 8253 8254 /** 8255 * <p>Strips any of a set of characters from the start and end of every 8256 * String in an array.</p> 8257 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8258 * 8259 * <p>A new array is returned each time, except for length zero. 8260 * A {@code null} array will return {@code null}. 8261 * An empty array will return itself. 8262 * A {@code null} array entry will be ignored. 8263 * A {@code null} stripChars will strip whitespace as defined by 8264 * {@link Character#isWhitespace(char)}.</p> 8265 * 8266 * <pre> 8267 * StringUtils.stripAll(null, *) = null 8268 * StringUtils.stripAll([], *) = [] 8269 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 8270 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 8271 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 8272 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 8273 * </pre> 8274 * 8275 * @param strs the array to remove characters from, may be null 8276 * @param stripChars the characters to remove, null treated as whitespace 8277 * @return the stripped Strings, {@code null} if null array input 8278 */ 8279 public static String[] stripAll(final String[] strs, final String stripChars) { 8280 final int strsLen = ArrayUtils.getLength(strs); 8281 if (strsLen == 0) { 8282 return strs; 8283 } 8284 final String[] newArr = new String[strsLen]; 8285 for (int i = 0; i < strsLen; i++) { 8286 newArr[i] = strip(strs[i], stripChars); 8287 } 8288 return newArr; 8289 } 8290 8291 /** 8292 * <p>Strips any of a set of characters from the end of a String.</p> 8293 * 8294 * <p>A {@code null} input String returns {@code null}. 8295 * An empty string ("") input returns the empty string.</p> 8296 * 8297 * <p>If the stripChars String is {@code null}, whitespace is 8298 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 8299 * 8300 * <pre> 8301 * StringUtils.stripEnd(null, *) = null 8302 * StringUtils.stripEnd("", *) = "" 8303 * StringUtils.stripEnd("abc", "") = "abc" 8304 * StringUtils.stripEnd("abc", null) = "abc" 8305 * StringUtils.stripEnd(" abc", null) = " abc" 8306 * StringUtils.stripEnd("abc ", null) = "abc" 8307 * StringUtils.stripEnd(" abc ", null) = " abc" 8308 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 8309 * StringUtils.stripEnd("120.00", ".0") = "12" 8310 * </pre> 8311 * 8312 * @param str the String to remove characters from, may be null 8313 * @param stripChars the set of characters to remove, null treated as whitespace 8314 * @return the stripped String, {@code null} if null String input 8315 */ 8316 public static String stripEnd(final String str, final String stripChars) { 8317 int end = length(str); 8318 if (end == 0) { 8319 return str; 8320 } 8321 8322 if (stripChars == null) { 8323 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 8324 end--; 8325 } 8326 } else if (stripChars.isEmpty()) { 8327 return str; 8328 } else { 8329 while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { 8330 end--; 8331 } 8332 } 8333 return str.substring(0, end); 8334 } 8335 8336 /** 8337 * <p>Strips any of a set of characters from the start of a String.</p> 8338 * 8339 * <p>A {@code null} input String returns {@code null}. 8340 * An empty string ("") input returns the empty string.</p> 8341 * 8342 * <p>If the stripChars String is {@code null}, whitespace is 8343 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 8344 * 8345 * <pre> 8346 * StringUtils.stripStart(null, *) = null 8347 * StringUtils.stripStart("", *) = "" 8348 * StringUtils.stripStart("abc", "") = "abc" 8349 * StringUtils.stripStart("abc", null) = "abc" 8350 * StringUtils.stripStart(" abc", null) = "abc" 8351 * StringUtils.stripStart("abc ", null) = "abc " 8352 * StringUtils.stripStart(" abc ", null) = "abc " 8353 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 8354 * </pre> 8355 * 8356 * @param str the String to remove characters from, may be null 8357 * @param stripChars the characters to remove, null treated as whitespace 8358 * @return the stripped String, {@code null} if null String input 8359 */ 8360 public static String stripStart(final String str, final String stripChars) { 8361 final int strLen = length(str); 8362 if (strLen == 0) { 8363 return str; 8364 } 8365 int start = 0; 8366 if (stripChars == null) { 8367 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 8368 start++; 8369 } 8370 } else if (stripChars.isEmpty()) { 8371 return str; 8372 } else { 8373 while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) { 8374 start++; 8375 } 8376 } 8377 return str.substring(start); 8378 } 8379 8380 /** 8381 * <p>Strips whitespace from the start and end of a String returning 8382 * an empty String if {@code null} input.</p> 8383 * 8384 * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace. 8385 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8386 * 8387 * <pre> 8388 * StringUtils.stripToEmpty(null) = "" 8389 * StringUtils.stripToEmpty("") = "" 8390 * StringUtils.stripToEmpty(" ") = "" 8391 * StringUtils.stripToEmpty("abc") = "abc" 8392 * StringUtils.stripToEmpty(" abc") = "abc" 8393 * StringUtils.stripToEmpty("abc ") = "abc" 8394 * StringUtils.stripToEmpty(" abc ") = "abc" 8395 * StringUtils.stripToEmpty(" ab c ") = "ab c" 8396 * </pre> 8397 * 8398 * @param str the String to be stripped, may be null 8399 * @return the trimmed String, or an empty String if {@code null} input 8400 * @since 2.0 8401 */ 8402 public static String stripToEmpty(final String str) { 8403 return str == null ? EMPTY : strip(str, null); 8404 } 8405 8406 /** 8407 * <p>Strips whitespace from the start and end of a String returning 8408 * {@code null} if the String is empty ("") after the strip.</p> 8409 * 8410 * <p>This is similar to {@link #trimToNull(String)} but removes whitespace. 8411 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8412 * 8413 * <pre> 8414 * StringUtils.stripToNull(null) = null 8415 * StringUtils.stripToNull("") = null 8416 * StringUtils.stripToNull(" ") = null 8417 * StringUtils.stripToNull("abc") = "abc" 8418 * StringUtils.stripToNull(" abc") = "abc" 8419 * StringUtils.stripToNull("abc ") = "abc" 8420 * StringUtils.stripToNull(" abc ") = "abc" 8421 * StringUtils.stripToNull(" ab c ") = "ab c" 8422 * </pre> 8423 * 8424 * @param str the String to be stripped, may be null 8425 * @return the stripped String, 8426 * {@code null} if whitespace, empty or null String input 8427 * @since 2.0 8428 */ 8429 public static String stripToNull(String str) { 8430 if (str == null) { 8431 return null; 8432 } 8433 str = strip(str, null); 8434 return str.isEmpty() ? null : str; 8435 } 8436 8437 // Substring 8438 //----------------------------------------------------------------------- 8439 /** 8440 * <p>Gets a substring from the specified String avoiding exceptions.</p> 8441 * 8442 * <p>A negative start position can be used to start {@code n} 8443 * characters from the end of the String.</p> 8444 * 8445 * <p>A {@code null} String will return {@code null}. 8446 * An empty ("") String will return "".</p> 8447 * 8448 * <pre> 8449 * StringUtils.substring(null, *) = null 8450 * StringUtils.substring("", *) = "" 8451 * StringUtils.substring("abc", 0) = "abc" 8452 * StringUtils.substring("abc", 2) = "c" 8453 * StringUtils.substring("abc", 4) = "" 8454 * StringUtils.substring("abc", -2) = "bc" 8455 * StringUtils.substring("abc", -4) = "abc" 8456 * </pre> 8457 * 8458 * @param str the String to get the substring from, may be null 8459 * @param start the position to start from, negative means 8460 * count back from the end of the String by this many characters 8461 * @return substring from start position, {@code null} if null String input 8462 */ 8463 public static String substring(final String str, int start) { 8464 if (str == null) { 8465 return null; 8466 } 8467 8468 // handle negatives, which means last n characters 8469 if (start < 0) { 8470 start = str.length() + start; // remember start is negative 8471 } 8472 8473 if (start < 0) { 8474 start = 0; 8475 } 8476 if (start > str.length()) { 8477 return EMPTY; 8478 } 8479 8480 return str.substring(start); 8481 } 8482 8483 /** 8484 * <p>Gets a substring from the specified String avoiding exceptions.</p> 8485 * 8486 * <p>A negative start position can be used to start/end {@code n} 8487 * characters from the end of the String.</p> 8488 * 8489 * <p>The returned substring starts with the character in the {@code start} 8490 * position and ends before the {@code end} position. All position counting is 8491 * zero-based -- i.e., to start at the beginning of the string use 8492 * {@code start = 0}. Negative start and end positions can be used to 8493 * specify offsets relative to the end of the String.</p> 8494 * 8495 * <p>If {@code start} is not strictly to the left of {@code end}, "" 8496 * is returned.</p> 8497 * 8498 * <pre> 8499 * StringUtils.substring(null, *, *) = null 8500 * StringUtils.substring("", * , *) = ""; 8501 * StringUtils.substring("abc", 0, 2) = "ab" 8502 * StringUtils.substring("abc", 2, 0) = "" 8503 * StringUtils.substring("abc", 2, 4) = "c" 8504 * StringUtils.substring("abc", 4, 6) = "" 8505 * StringUtils.substring("abc", 2, 2) = "" 8506 * StringUtils.substring("abc", -2, -1) = "b" 8507 * StringUtils.substring("abc", -4, 2) = "ab" 8508 * </pre> 8509 * 8510 * @param str the String to get the substring from, may be null 8511 * @param start the position to start from, negative means 8512 * count back from the end of the String by this many characters 8513 * @param end the position to end at (exclusive), negative means 8514 * count back from the end of the String by this many characters 8515 * @return substring from start position to end position, 8516 * {@code null} if null String input 8517 */ 8518 public static String substring(final String str, int start, int end) { 8519 if (str == null) { 8520 return null; 8521 } 8522 8523 // handle negatives 8524 if (end < 0) { 8525 end = str.length() + end; // remember end is negative 8526 } 8527 if (start < 0) { 8528 start = str.length() + start; // remember start is negative 8529 } 8530 8531 // check length next 8532 if (end > str.length()) { 8533 end = str.length(); 8534 } 8535 8536 // if start is greater than end, return "" 8537 if (start > end) { 8538 return EMPTY; 8539 } 8540 8541 if (start < 0) { 8542 start = 0; 8543 } 8544 if (end < 0) { 8545 end = 0; 8546 } 8547 8548 return str.substring(start, end); 8549 } 8550 8551 /** 8552 * <p>Gets the substring after the first occurrence of a separator. 8553 * The separator is not returned.</p> 8554 * 8555 * <p>A {@code null} string input will return {@code null}. 8556 * An empty ("") string input will return the empty string. 8557 * 8558 * <p>If nothing is found, the empty string is returned.</p> 8559 * 8560 * <pre> 8561 * StringUtils.substringAfter(null, *) = null 8562 * StringUtils.substringAfter("", *) = "" 8563 * StringUtils.substringAfter("abc", 'a') = "bc" 8564 * StringUtils.substringAfter("abcba", 'b') = "cba" 8565 * StringUtils.substringAfter("abc", 'c') = "" 8566 * StringUtils.substringAfter("abc", 'd') = "" 8567 * StringUtils.substringAfter(" abc", 32) = "abc" 8568 * </pre> 8569 * 8570 * @param str the String to get a substring from, may be null 8571 * @param separator the character to search. 8572 * @return the substring after the first occurrence of the separator, 8573 * {@code null} if null String input 8574 * @since 3.11 8575 */ 8576 public static String substringAfter(final String str, final int separator) { 8577 if (isEmpty(str)) { 8578 return str; 8579 } 8580 final int pos = str.indexOf(separator); 8581 if (pos == INDEX_NOT_FOUND) { 8582 return EMPTY; 8583 } 8584 return str.substring(pos + 1); 8585 } 8586 8587 /** 8588 * <p>Gets the substring after the first occurrence of a separator. 8589 * The separator is not returned.</p> 8590 * 8591 * <p>A {@code null} string input will return {@code null}. 8592 * An empty ("") string input will return the empty string. 8593 * A {@code null} separator will return the empty string if the 8594 * input string is not {@code null}.</p> 8595 * 8596 * <p>If nothing is found, the empty string is returned.</p> 8597 * 8598 * <pre> 8599 * StringUtils.substringAfter(null, *) = null 8600 * StringUtils.substringAfter("", *) = "" 8601 * StringUtils.substringAfter(*, null) = "" 8602 * StringUtils.substringAfter("abc", "a") = "bc" 8603 * StringUtils.substringAfter("abcba", "b") = "cba" 8604 * StringUtils.substringAfter("abc", "c") = "" 8605 * StringUtils.substringAfter("abc", "d") = "" 8606 * StringUtils.substringAfter("abc", "") = "abc" 8607 * </pre> 8608 * 8609 * @param str the String to get a substring from, may be null 8610 * @param separator the String to search for, may be null 8611 * @return the substring after the first occurrence of the separator, 8612 * {@code null} if null String input 8613 * @since 2.0 8614 */ 8615 public static String substringAfter(final String str, final String separator) { 8616 if (isEmpty(str)) { 8617 return str; 8618 } 8619 if (separator == null) { 8620 return EMPTY; 8621 } 8622 final int pos = str.indexOf(separator); 8623 if (pos == INDEX_NOT_FOUND) { 8624 return EMPTY; 8625 } 8626 return str.substring(pos + separator.length()); 8627 } 8628 8629 // startsWith 8630 //----------------------------------------------------------------------- 8631 8632 /** 8633 * <p>Gets the substring after the last occurrence of a separator. 8634 * The separator is not returned.</p> 8635 * 8636 * <p>A {@code null} string input will return {@code null}. 8637 * An empty ("") string input will return the empty string. 8638 * 8639 * <p>If nothing is found, the empty string is returned.</p> 8640 * 8641 * <pre> 8642 * StringUtils.substringAfterLast(null, *) = null 8643 * StringUtils.substringAfterLast("", *) = "" 8644 * StringUtils.substringAfterLast("abc", 'a') = "bc" 8645 * StringUtils.substringAfterLast(" bc", 32) = "bc" 8646 * StringUtils.substringAfterLast("abcba", 'b') = "a" 8647 * StringUtils.substringAfterLast("abc", 'c') = "" 8648 * StringUtils.substringAfterLast("a", 'a') = "" 8649 * StringUtils.substringAfterLast("a", 'z') = "" 8650 * </pre> 8651 * 8652 * @param str the String to get a substring from, may be null 8653 * @param separator the String to search for, may be null 8654 * @return the substring after the last occurrence of the separator, 8655 * {@code null} if null String input 8656 * @since 3.11 8657 */ 8658 public static String substringAfterLast(final String str, final int separator) { 8659 if (isEmpty(str)) { 8660 return str; 8661 } 8662 final int pos = str.lastIndexOf(separator); 8663 if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) { 8664 return EMPTY; 8665 } 8666 return str.substring(pos + 1); 8667 } 8668 8669 /** 8670 * <p>Gets the substring after the last occurrence of a separator. 8671 * The separator is not returned.</p> 8672 * 8673 * <p>A {@code null} string input will return {@code null}. 8674 * An empty ("") string input will return the empty string. 8675 * An empty or {@code null} separator will return the empty string if 8676 * the input string is not {@code null}.</p> 8677 * 8678 * <p>If nothing is found, the empty string is returned.</p> 8679 * 8680 * <pre> 8681 * StringUtils.substringAfterLast(null, *) = null 8682 * StringUtils.substringAfterLast("", *) = "" 8683 * StringUtils.substringAfterLast(*, "") = "" 8684 * StringUtils.substringAfterLast(*, null) = "" 8685 * StringUtils.substringAfterLast("abc", "a") = "bc" 8686 * StringUtils.substringAfterLast("abcba", "b") = "a" 8687 * StringUtils.substringAfterLast("abc", "c") = "" 8688 * StringUtils.substringAfterLast("a", "a") = "" 8689 * StringUtils.substringAfterLast("a", "z") = "" 8690 * </pre> 8691 * 8692 * @param str the String to get a substring from, may be null 8693 * @param separator the String to search for, may be null 8694 * @return the substring after the last occurrence of the separator, 8695 * {@code null} if null String input 8696 * @since 2.0 8697 */ 8698 public static String substringAfterLast(final String str, final String separator) { 8699 if (isEmpty(str)) { 8700 return str; 8701 } 8702 if (isEmpty(separator)) { 8703 return EMPTY; 8704 } 8705 final int pos = str.lastIndexOf(separator); 8706 if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) { 8707 return EMPTY; 8708 } 8709 return str.substring(pos + separator.length()); 8710 } 8711 8712 // SubStringAfter/SubStringBefore 8713 //----------------------------------------------------------------------- 8714 /** 8715 * <p>Gets the substring before the first occurrence of a separator. 8716 * The separator is not returned.</p> 8717 * 8718 * <p>A {@code null} string input will return {@code null}. 8719 * An empty ("") string input will return the empty string. 8720 * A {@code null} separator will return the input string.</p> 8721 * 8722 * <p>If nothing is found, the string input is returned.</p> 8723 * 8724 * <pre> 8725 * StringUtils.substringBefore(null, *) = null 8726 * StringUtils.substringBefore("", *) = "" 8727 * StringUtils.substringBefore("abc", "a") = "" 8728 * StringUtils.substringBefore("abcba", "b") = "a" 8729 * StringUtils.substringBefore("abc", "c") = "ab" 8730 * StringUtils.substringBefore("abc", "d") = "abc" 8731 * StringUtils.substringBefore("abc", "") = "" 8732 * StringUtils.substringBefore("abc", null) = "abc" 8733 * </pre> 8734 * 8735 * @param str the String to get a substring from, may be null 8736 * @param separator the String to search for, may be null 8737 * @return the substring before the first occurrence of the separator, 8738 * {@code null} if null String input 8739 * @since 2.0 8740 */ 8741 public static String substringBefore(final String str, final String separator) { 8742 if (isEmpty(str) || separator == null) { 8743 return str; 8744 } 8745 if (separator.isEmpty()) { 8746 return EMPTY; 8747 } 8748 final int pos = str.indexOf(separator); 8749 if (pos == INDEX_NOT_FOUND) { 8750 return str; 8751 } 8752 return str.substring(0, pos); 8753 } 8754 8755 /** 8756 * <p>Gets the substring before the last occurrence of a separator. 8757 * The separator is not returned.</p> 8758 * 8759 * <p>A {@code null} string input will return {@code null}. 8760 * An empty ("") string input will return the empty string. 8761 * An empty or {@code null} separator will return the input string.</p> 8762 * 8763 * <p>If nothing is found, the string input is returned.</p> 8764 * 8765 * <pre> 8766 * StringUtils.substringBeforeLast(null, *) = null 8767 * StringUtils.substringBeforeLast("", *) = "" 8768 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 8769 * StringUtils.substringBeforeLast("abc", "c") = "ab" 8770 * StringUtils.substringBeforeLast("a", "a") = "" 8771 * StringUtils.substringBeforeLast("a", "z") = "a" 8772 * StringUtils.substringBeforeLast("a", null) = "a" 8773 * StringUtils.substringBeforeLast("a", "") = "a" 8774 * </pre> 8775 * 8776 * @param str the String to get a substring from, may be null 8777 * @param separator the String to search for, may be null 8778 * @return the substring before the last occurrence of the separator, 8779 * {@code null} if null String input 8780 * @since 2.0 8781 */ 8782 public static String substringBeforeLast(final String str, final String separator) { 8783 if (isEmpty(str) || isEmpty(separator)) { 8784 return str; 8785 } 8786 final int pos = str.lastIndexOf(separator); 8787 if (pos == INDEX_NOT_FOUND) { 8788 return str; 8789 } 8790 return str.substring(0, pos); 8791 } 8792 8793 // Substring between 8794 //----------------------------------------------------------------------- 8795 /** 8796 * <p>Gets the String that is nested in between two instances of the 8797 * same String.</p> 8798 * 8799 * <p>A {@code null} input String returns {@code null}. 8800 * A {@code null} tag returns {@code null}.</p> 8801 * 8802 * <pre> 8803 * StringUtils.substringBetween(null, *) = null 8804 * StringUtils.substringBetween("", "") = "" 8805 * StringUtils.substringBetween("", "tag") = null 8806 * StringUtils.substringBetween("tagabctag", null) = null 8807 * StringUtils.substringBetween("tagabctag", "") = "" 8808 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 8809 * </pre> 8810 * 8811 * @param str the String containing the substring, may be null 8812 * @param tag the String before and after the substring, may be null 8813 * @return the substring, {@code null} if no match 8814 * @since 2.0 8815 */ 8816 public static String substringBetween(final String str, final String tag) { 8817 return substringBetween(str, tag, tag); 8818 } 8819 8820 // endsWith 8821 //----------------------------------------------------------------------- 8822 8823 /** 8824 * <p>Gets the String that is nested in between two Strings. 8825 * Only the first match is returned.</p> 8826 * 8827 * <p>A {@code null} input String returns {@code null}. 8828 * A {@code null} open/close returns {@code null} (no match). 8829 * An empty ("") open and close returns an empty string.</p> 8830 * 8831 * <pre> 8832 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 8833 * StringUtils.substringBetween(null, *, *) = null 8834 * StringUtils.substringBetween(*, null, *) = null 8835 * StringUtils.substringBetween(*, *, null) = null 8836 * StringUtils.substringBetween("", "", "") = "" 8837 * StringUtils.substringBetween("", "", "]") = null 8838 * StringUtils.substringBetween("", "[", "]") = null 8839 * StringUtils.substringBetween("yabcz", "", "") = "" 8840 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 8841 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 8842 * </pre> 8843 * 8844 * @param str the String containing the substring, may be null 8845 * @param open the String before the substring, may be null 8846 * @param close the String after the substring, may be null 8847 * @return the substring, {@code null} if no match 8848 * @since 2.0 8849 */ 8850 public static String substringBetween(final String str, final String open, final String close) { 8851 if (!ObjectUtils.allNotNull(str, open, close)) { 8852 return null; 8853 } 8854 final int start = str.indexOf(open); 8855 if (start != INDEX_NOT_FOUND) { 8856 final int end = str.indexOf(close, start + open.length()); 8857 if (end != INDEX_NOT_FOUND) { 8858 return str.substring(start + open.length(), end); 8859 } 8860 } 8861 return null; 8862 } 8863 8864 /** 8865 * <p>Searches a String for substrings delimited by a start and end tag, 8866 * returning all matching substrings in an array.</p> 8867 * 8868 * <p>A {@code null} input String returns {@code null}. 8869 * A {@code null} open/close returns {@code null} (no match). 8870 * An empty ("") open/close returns {@code null} (no match).</p> 8871 * 8872 * <pre> 8873 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 8874 * StringUtils.substringsBetween(null, *, *) = null 8875 * StringUtils.substringsBetween(*, null, *) = null 8876 * StringUtils.substringsBetween(*, *, null) = null 8877 * StringUtils.substringsBetween("", "[", "]") = [] 8878 * </pre> 8879 * 8880 * @param str the String containing the substrings, null returns null, empty returns empty 8881 * @param open the String identifying the start of the substring, empty returns null 8882 * @param close the String identifying the end of the substring, empty returns null 8883 * @return a String Array of substrings, or {@code null} if no match 8884 * @since 2.3 8885 */ 8886 public static String[] substringsBetween(final String str, final String open, final String close) { 8887 if (str == null || isEmpty(open) || isEmpty(close)) { 8888 return null; 8889 } 8890 final int strLen = str.length(); 8891 if (strLen == 0) { 8892 return ArrayUtils.EMPTY_STRING_ARRAY; 8893 } 8894 final int closeLen = close.length(); 8895 final int openLen = open.length(); 8896 final List<String> list = new ArrayList<>(); 8897 int pos = 0; 8898 while (pos < strLen - closeLen) { 8899 int start = str.indexOf(open, pos); 8900 if (start < 0) { 8901 break; 8902 } 8903 start += openLen; 8904 final int end = str.indexOf(close, start); 8905 if (end < 0) { 8906 break; 8907 } 8908 list.add(str.substring(start, end)); 8909 pos = end + closeLen; 8910 } 8911 if (list.isEmpty()) { 8912 return null; 8913 } 8914 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8915 } 8916 8917 /** 8918 * <p>Swaps the case of a String changing upper and title case to 8919 * lower case, and lower case to upper case.</p> 8920 * 8921 * <ul> 8922 * <li>Upper case character converts to Lower case</li> 8923 * <li>Title case character converts to Lower case</li> 8924 * <li>Lower case character converts to Upper case</li> 8925 * </ul> 8926 * 8927 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#swapCase(String)}. 8928 * A {@code null} input String returns {@code null}.</p> 8929 * 8930 * <pre> 8931 * StringUtils.swapCase(null) = null 8932 * StringUtils.swapCase("") = "" 8933 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 8934 * </pre> 8935 * 8936 * <p>NOTE: This method changed in Lang version 2.0. 8937 * It no longer performs a word based algorithm. 8938 * If you only use ASCII, you will notice no change. 8939 * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p> 8940 * 8941 * @param str the String to swap case, may be null 8942 * @return the changed String, {@code null} if null String input 8943 */ 8944 public static String swapCase(final String str) { 8945 if (isEmpty(str)) { 8946 return str; 8947 } 8948 8949 final int strLen = str.length(); 8950 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 8951 int outOffset = 0; 8952 for (int i = 0; i < strLen; ) { 8953 final int oldCodepoint = str.codePointAt(i); 8954 final int newCodePoint; 8955 if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) { 8956 newCodePoint = Character.toLowerCase(oldCodepoint); 8957 } else if (Character.isLowerCase(oldCodepoint)) { 8958 newCodePoint = Character.toUpperCase(oldCodepoint); 8959 } else { 8960 newCodePoint = oldCodepoint; 8961 } 8962 newCodePoints[outOffset++] = newCodePoint; 8963 i += Character.charCount(newCodePoint); 8964 } 8965 return new String(newCodePoints, 0, outOffset); 8966 } 8967 8968 /** 8969 * <p>Converts a {@code CharSequence} into an array of code points.</p> 8970 * 8971 * <p>Valid pairs of surrogate code units will be converted into a single supplementary 8972 * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or 8973 * a low surrogate not preceded by a high surrogate) will be returned as-is.</p> 8974 * 8975 * <pre> 8976 * StringUtils.toCodePoints(null) = null 8977 * StringUtils.toCodePoints("") = [] // empty array 8978 * </pre> 8979 * 8980 * @param str the character sequence to convert 8981 * @return an array of code points 8982 * @since 3.6 8983 */ 8984 public static int[] toCodePoints(final CharSequence str) { 8985 if (str == null) { 8986 return null; 8987 } 8988 if (str.length() == 0) { 8989 return ArrayUtils.EMPTY_INT_ARRAY; 8990 } 8991 8992 final String s = str.toString(); 8993 final int[] result = new int[s.codePointCount(0, s.length())]; 8994 int index = 0; 8995 for (int i = 0; i < result.length; i++) { 8996 result[i] = s.codePointAt(index); 8997 index += Character.charCount(result[i]); 8998 } 8999 return result; 9000 } 9001 9002 /** 9003 * Converts a {@code byte[]} to a String using the specified character encoding. 9004 * 9005 * @param bytes 9006 * the byte array to read from 9007 * @param charset 9008 * the encoding to use, if null then use the platform default 9009 * @return a new String 9010 * @throws NullPointerException 9011 * if {@code bytes} is null 9012 * @since 3.2 9013 * @since 3.3 No longer throws {@link UnsupportedEncodingException}. 9014 */ 9015 public static String toEncodedString(final byte[] bytes, final Charset charset) { 9016 return new String(bytes, Charsets.toCharset(charset)); 9017 } 9018 9019 /** 9020 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner. 9021 * 9022 * @param source A source String or null. 9023 * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null. 9024 * @since 3.10 9025 */ 9026 public static String toRootLowerCase(final String source) { 9027 return source == null ? null : source.toLowerCase(Locale.ROOT); 9028 } 9029 9030 /** 9031 * Converts the given source String as a upper-case using the {@link Locale#ROOT} locale in a null-safe manner. 9032 * 9033 * @param source A source String or null. 9034 * @return the given source String as a upper-case using the {@link Locale#ROOT} locale or null. 9035 * @since 3.10 9036 */ 9037 public static String toRootUpperCase(final String source) { 9038 return source == null ? null : source.toUpperCase(Locale.ROOT); 9039 } 9040 9041 /** 9042 * Converts a {@code byte[]} to a String using the specified character encoding. 9043 * 9044 * @param bytes 9045 * the byte array to read from 9046 * @param charsetName 9047 * the encoding to use, if null then use the platform default 9048 * @return a new String 9049 * @throws UnsupportedEncodingException 9050 * If the named charset is not supported 9051 * @throws NullPointerException 9052 * if the input is null 9053 * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code 9054 * @since 3.1 9055 */ 9056 @Deprecated 9057 public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException { 9058 return charsetName != null ? new String(bytes, charsetName) : new String(bytes, Charset.defaultCharset()); 9059 } 9060 9061 // Trim 9062 //----------------------------------------------------------------------- 9063 /** 9064 * <p>Removes control characters (char <= 32) from both 9065 * ends of this String, handling {@code null} by returning 9066 * {@code null}.</p> 9067 * 9068 * <p>The String is trimmed using {@link String#trim()}. 9069 * Trim removes start and end characters <= 32. 9070 * To strip whitespace use {@link #strip(String)}.</p> 9071 * 9072 * <p>To trim your choice of characters, use the 9073 * {@link #strip(String, String)} methods.</p> 9074 * 9075 * <pre> 9076 * StringUtils.trim(null) = null 9077 * StringUtils.trim("") = "" 9078 * StringUtils.trim(" ") = "" 9079 * StringUtils.trim("abc") = "abc" 9080 * StringUtils.trim(" abc ") = "abc" 9081 * </pre> 9082 * 9083 * @param str the String to be trimmed, may be null 9084 * @return the trimmed string, {@code null} if null String input 9085 */ 9086 public static String trim(final String str) { 9087 return str == null ? null : str.trim(); 9088 } 9089 9090 /** 9091 * <p>Removes control characters (char <= 32) from both 9092 * ends of this String returning an empty String ("") if the String 9093 * is empty ("") after the trim or if it is {@code null}. 9094 * 9095 * <p>The String is trimmed using {@link String#trim()}. 9096 * Trim removes start and end characters <= 32. 9097 * To strip whitespace use {@link #stripToEmpty(String)}.</p> 9098 * 9099 * <pre> 9100 * StringUtils.trimToEmpty(null) = "" 9101 * StringUtils.trimToEmpty("") = "" 9102 * StringUtils.trimToEmpty(" ") = "" 9103 * StringUtils.trimToEmpty("abc") = "abc" 9104 * StringUtils.trimToEmpty(" abc ") = "abc" 9105 * </pre> 9106 * 9107 * @param str the String to be trimmed, may be null 9108 * @return the trimmed String, or an empty String if {@code null} input 9109 * @since 2.0 9110 */ 9111 public static String trimToEmpty(final String str) { 9112 return str == null ? EMPTY : str.trim(); 9113 } 9114 9115 /** 9116 * <p>Removes control characters (char <= 32) from both 9117 * ends of this String returning {@code null} if the String is 9118 * empty ("") after the trim or if it is {@code null}. 9119 * 9120 * <p>The String is trimmed using {@link String#trim()}. 9121 * Trim removes start and end characters <= 32. 9122 * To strip whitespace use {@link #stripToNull(String)}.</p> 9123 * 9124 * <pre> 9125 * StringUtils.trimToNull(null) = null 9126 * StringUtils.trimToNull("") = null 9127 * StringUtils.trimToNull(" ") = null 9128 * StringUtils.trimToNull("abc") = "abc" 9129 * StringUtils.trimToNull(" abc ") = "abc" 9130 * </pre> 9131 * 9132 * @param str the String to be trimmed, may be null 9133 * @return the trimmed String, 9134 * {@code null} if only chars <= 32, empty or null String input 9135 * @since 2.0 9136 */ 9137 public static String trimToNull(final String str) { 9138 final String ts = trim(str); 9139 return isEmpty(ts) ? null : ts; 9140 } 9141 9142 /** 9143 * <p>Truncates a String. This will turn 9144 * "Now is the time for all good men" into "Now is the time for".</p> 9145 * 9146 * <p>Specifically:</p> 9147 * <ul> 9148 * <li>If {@code str} is less than {@code maxWidth} characters 9149 * long, return it.</li> 9150 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li> 9151 * <li>If {@code maxWidth} is less than {@code 0}, throw an 9152 * {@code IllegalArgumentException}.</li> 9153 * <li>In no case will it return a String of length greater than 9154 * {@code maxWidth}.</li> 9155 * </ul> 9156 * 9157 * <pre> 9158 * StringUtils.truncate(null, 0) = null 9159 * StringUtils.truncate(null, 2) = null 9160 * StringUtils.truncate("", 4) = "" 9161 * StringUtils.truncate("abcdefg", 4) = "abcd" 9162 * StringUtils.truncate("abcdefg", 6) = "abcdef" 9163 * StringUtils.truncate("abcdefg", 7) = "abcdefg" 9164 * StringUtils.truncate("abcdefg", 8) = "abcdefg" 9165 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException 9166 * </pre> 9167 * 9168 * @param str the String to truncate, may be null 9169 * @param maxWidth maximum length of result String, must be positive 9170 * @return truncated String, {@code null} if null String input 9171 * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0} 9172 * @since 3.5 9173 */ 9174 public static String truncate(final String str, final int maxWidth) { 9175 return truncate(str, 0, maxWidth); 9176 } 9177 9178 /** 9179 * <p>Truncates a String. This will turn 9180 * "Now is the time for all good men" into "is the time for all".</p> 9181 * 9182 * <p>Works like {@code truncate(String, int)}, but allows you to specify 9183 * a "left edge" offset. 9184 * 9185 * <p>Specifically:</p> 9186 * <ul> 9187 * <li>If {@code str} is less than {@code maxWidth} characters 9188 * long, return it.</li> 9189 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li> 9190 * <li>If {@code maxWidth} is less than {@code 0}, throw an 9191 * {@code IllegalArgumentException}.</li> 9192 * <li>If {@code offset} is less than {@code 0}, throw an 9193 * {@code IllegalArgumentException}.</li> 9194 * <li>In no case will it return a String of length greater than 9195 * {@code maxWidth}.</li> 9196 * </ul> 9197 * 9198 * <pre> 9199 * StringUtils.truncate(null, 0, 0) = null 9200 * StringUtils.truncate(null, 2, 4) = null 9201 * StringUtils.truncate("", 0, 10) = "" 9202 * StringUtils.truncate("", 2, 10) = "" 9203 * StringUtils.truncate("abcdefghij", 0, 3) = "abc" 9204 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij" 9205 * StringUtils.truncate("raspberry peach", 10, 15) = "peach" 9206 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" 9207 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException 9208 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException 9209 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException 9210 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" 9211 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" 9212 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" 9213 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" 9214 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" 9215 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" 9216 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" 9217 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" 9218 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" 9219 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" 9220 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" 9221 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" 9222 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" 9223 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" 9224 * StringUtils.truncate("abcdefghijklmno", 15, 1) = "" 9225 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" 9226 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" 9227 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException 9228 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException 9229 * </pre> 9230 * 9231 * @param str the String to truncate, may be null 9232 * @param offset left edge of source String 9233 * @param maxWidth maximum length of result String, must be positive 9234 * @return truncated String, {@code null} if null String input 9235 * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0} 9236 * @since 3.5 9237 */ 9238 public static String truncate(final String str, final int offset, final int maxWidth) { 9239 if (offset < 0) { 9240 throw new IllegalArgumentException("offset cannot be negative"); 9241 } 9242 if (maxWidth < 0) { 9243 throw new IllegalArgumentException("maxWith cannot be negative"); 9244 } 9245 if (str == null) { 9246 return null; 9247 } 9248 if (offset > str.length()) { 9249 return EMPTY; 9250 } 9251 if (str.length() > maxWidth) { 9252 final int ix = Math.min(offset + maxWidth, str.length()); 9253 return str.substring(offset, ix); 9254 } 9255 return str.substring(offset); 9256 } 9257 9258 /** 9259 * <p>Uncapitalizes a String, changing the first character to lower case as 9260 * per {@link Character#toLowerCase(int)}. No other characters are changed.</p> 9261 * 9262 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String)}. 9263 * A {@code null} input String returns {@code null}.</p> 9264 * 9265 * <pre> 9266 * StringUtils.uncapitalize(null) = null 9267 * StringUtils.uncapitalize("") = "" 9268 * StringUtils.uncapitalize("cat") = "cat" 9269 * StringUtils.uncapitalize("Cat") = "cat" 9270 * StringUtils.uncapitalize("CAT") = "cAT" 9271 * </pre> 9272 * 9273 * @param str the String to uncapitalize, may be null 9274 * @return the uncapitalized String, {@code null} if null String input 9275 * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String) 9276 * @see #capitalize(String) 9277 * @since 2.0 9278 */ 9279 public static String uncapitalize(final String str) { 9280 final int strLen = length(str); 9281 if (strLen == 0) { 9282 return str; 9283 } 9284 9285 final int firstCodepoint = str.codePointAt(0); 9286 final int newCodePoint = Character.toLowerCase(firstCodepoint); 9287 if (firstCodepoint == newCodePoint) { 9288 // already capitalized 9289 return str; 9290 } 9291 9292 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 9293 int outOffset = 0; 9294 newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint 9295 for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) { 9296 final int codepoint = str.codePointAt(inOffset); 9297 newCodePoints[outOffset++] = codepoint; // copy the remaining ones 9298 inOffset += Character.charCount(codepoint); 9299 } 9300 return new String(newCodePoints, 0, outOffset); 9301 } 9302 9303 /** 9304 * <p> 9305 * Unwraps a given string from a character. 9306 * </p> 9307 * 9308 * <pre> 9309 * StringUtils.unwrap(null, null) = null 9310 * StringUtils.unwrap(null, '\0') = null 9311 * StringUtils.unwrap(null, '1') = null 9312 * StringUtils.unwrap("a", 'a') = "a" 9313 * StringUtils.unwrap("aa", 'a') = "" 9314 * StringUtils.unwrap("\'abc\'", '\'') = "abc" 9315 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA" 9316 * StringUtils.unwrap("A", '#') = "A" 9317 * StringUtils.unwrap("#A", '#') = "#A" 9318 * StringUtils.unwrap("A#", '#') = "A#" 9319 * </pre> 9320 * 9321 * @param str 9322 * the String to be unwrapped, can be null 9323 * @param wrapChar 9324 * the character used to unwrap 9325 * @return unwrapped String or the original string 9326 * if it is not quoted properly with the wrapChar 9327 * @since 3.6 9328 */ 9329 public static String unwrap(final String str, final char wrapChar) { 9330 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) { 9331 return str; 9332 } 9333 9334 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) { 9335 final int startIndex = 0; 9336 final int endIndex = str.length() - 1; 9337 9338 return str.substring(startIndex + 1, endIndex); 9339 } 9340 9341 return str; 9342 } 9343 9344 /** 9345 * <p> 9346 * Unwraps a given string from anther string. 9347 * </p> 9348 * 9349 * <pre> 9350 * StringUtils.unwrap(null, null) = null 9351 * StringUtils.unwrap(null, "") = null 9352 * StringUtils.unwrap(null, "1") = null 9353 * StringUtils.unwrap("a", "a") = "a" 9354 * StringUtils.unwrap("aa", "a") = "" 9355 * StringUtils.unwrap("\'abc\'", "\'") = "abc" 9356 * StringUtils.unwrap("\"abc\"", "\"") = "abc" 9357 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB" 9358 * StringUtils.unwrap("A", "#") = "A" 9359 * StringUtils.unwrap("#A", "#") = "#A" 9360 * StringUtils.unwrap("A#", "#") = "A#" 9361 * </pre> 9362 * 9363 * @param str 9364 * the String to be unwrapped, can be null 9365 * @param wrapToken 9366 * the String used to unwrap 9367 * @return unwrapped String or the original string 9368 * if it is not quoted properly with the wrapToken 9369 * @since 3.6 9370 */ 9371 public static String unwrap(final String str, final String wrapToken) { 9372 if (isEmpty(str) || isEmpty(wrapToken) || str.length() == 1) { 9373 return str; 9374 } 9375 9376 if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) { 9377 final int startIndex = str.indexOf(wrapToken); 9378 final int endIndex = str.lastIndexOf(wrapToken); 9379 final int wrapLength = wrapToken.length(); 9380 9381 if (startIndex != -1 && endIndex != -1) { 9382 return str.substring(startIndex + wrapLength, endIndex); 9383 } 9384 } 9385 9386 return str; 9387 } 9388 9389 // Case conversion 9390 //----------------------------------------------------------------------- 9391 /** 9392 * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p> 9393 * 9394 * <p>A {@code null} input String returns {@code null}.</p> 9395 * 9396 * <pre> 9397 * StringUtils.upperCase(null) = null 9398 * StringUtils.upperCase("") = "" 9399 * StringUtils.upperCase("aBc") = "ABC" 9400 * </pre> 9401 * 9402 * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, 9403 * the result of this method is affected by the current locale. 9404 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 9405 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 9406 * 9407 * @param str the String to upper case, may be null 9408 * @return the upper cased String, {@code null} if null String input 9409 */ 9410 public static String upperCase(final String str) { 9411 if (str == null) { 9412 return null; 9413 } 9414 return str.toUpperCase(); 9415 } 9416 9417 /** 9418 * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p> 9419 * 9420 * <p>A {@code null} input String returns {@code null}.</p> 9421 * 9422 * <pre> 9423 * StringUtils.upperCase(null, Locale.ENGLISH) = null 9424 * StringUtils.upperCase("", Locale.ENGLISH) = "" 9425 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 9426 * </pre> 9427 * 9428 * @param str the String to upper case, may be null 9429 * @param locale the locale that defines the case transformation rules, must not be null 9430 * @return the upper cased String, {@code null} if null String input 9431 * @since 2.5 9432 */ 9433 public static String upperCase(final String str, final Locale locale) { 9434 if (str == null) { 9435 return null; 9436 } 9437 return str.toUpperCase(locale); 9438 } 9439 9440 /** 9441 * Returns the string representation of the {@code char} array or null. 9442 * 9443 * @param value the character array. 9444 * @return a String or null 9445 * @see String#valueOf(char[]) 9446 * @since 3.9 9447 */ 9448 public static String valueOf(final char[] value) { 9449 return value == null ? null : String.valueOf(value); 9450 } 9451 9452 /** 9453 * <p> 9454 * Wraps a string with a char. 9455 * </p> 9456 * 9457 * <pre> 9458 * StringUtils.wrap(null, *) = null 9459 * StringUtils.wrap("", *) = "" 9460 * StringUtils.wrap("ab", '\0') = "ab" 9461 * StringUtils.wrap("ab", 'x') = "xabx" 9462 * StringUtils.wrap("ab", '\'') = "'ab'" 9463 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\"" 9464 * </pre> 9465 * 9466 * @param str 9467 * the string to be wrapped, may be {@code null} 9468 * @param wrapWith 9469 * the char that will wrap {@code str} 9470 * @return the wrapped string, or {@code null} if {@code str==null} 9471 * @since 3.4 9472 */ 9473 public static String wrap(final String str, final char wrapWith) { 9474 9475 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9476 return str; 9477 } 9478 9479 return wrapWith + str + wrapWith; 9480 } 9481 9482 /** 9483 * <p> 9484 * Wraps a String with another String. 9485 * </p> 9486 * 9487 * <p> 9488 * A {@code null} input String returns {@code null}. 9489 * </p> 9490 * 9491 * <pre> 9492 * StringUtils.wrap(null, *) = null 9493 * StringUtils.wrap("", *) = "" 9494 * StringUtils.wrap("ab", null) = "ab" 9495 * StringUtils.wrap("ab", "x") = "xabx" 9496 * StringUtils.wrap("ab", "\"") = "\"ab\"" 9497 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\"" 9498 * StringUtils.wrap("ab", "'") = "'ab'" 9499 * StringUtils.wrap("'abcd'", "'") = "''abcd''" 9500 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'" 9501 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\"" 9502 * </pre> 9503 * 9504 * @param str 9505 * the String to be wrapper, may be null 9506 * @param wrapWith 9507 * the String that will wrap str 9508 * @return wrapped String, {@code null} if null String input 9509 * @since 3.4 9510 */ 9511 public static String wrap(final String str, final String wrapWith) { 9512 9513 if (isEmpty(str) || isEmpty(wrapWith)) { 9514 return str; 9515 } 9516 9517 return wrapWith.concat(str).concat(wrapWith); 9518 } 9519 9520 /** 9521 * <p> 9522 * Wraps a string with a char if that char is missing from the start or end of the given string. 9523 * </p> 9524 * 9525 * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p> 9526 * 9527 * <pre> 9528 * StringUtils.wrapIfMissing(null, *) = null 9529 * StringUtils.wrapIfMissing("", *) = "" 9530 * StringUtils.wrapIfMissing("ab", '\0') = "ab" 9531 * StringUtils.wrapIfMissing("ab", 'x') = "xabx" 9532 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'" 9533 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\"" 9534 * StringUtils.wrapIfMissing("/", '/') = "/" 9535 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/" 9536 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/" 9537 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/" 9538 * </pre> 9539 * 9540 * @param str 9541 * the string to be wrapped, may be {@code null} 9542 * @param wrapWith 9543 * the char that will wrap {@code str} 9544 * @return the wrapped string, or {@code null} if {@code str==null} 9545 * @since 3.5 9546 */ 9547 public static String wrapIfMissing(final String str, final char wrapWith) { 9548 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9549 return str; 9550 } 9551 final boolean wrapStart = str.charAt(0) != wrapWith; 9552 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith; 9553 if (!wrapStart && !wrapEnd) { 9554 return str; 9555 } 9556 9557 final StringBuilder builder = new StringBuilder(str.length() + 2); 9558 if (wrapStart) { 9559 builder.append(wrapWith); 9560 } 9561 builder.append(str); 9562 if (wrapEnd) { 9563 builder.append(wrapWith); 9564 } 9565 return builder.toString(); 9566 } 9567 9568 /** 9569 * <p> 9570 * Wraps a string with a string if that string is missing from the start or end of the given string. 9571 * </p> 9572 * 9573 * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p> 9574 * 9575 * <pre> 9576 * StringUtils.wrapIfMissing(null, *) = null 9577 * StringUtils.wrapIfMissing("", *) = "" 9578 * StringUtils.wrapIfMissing("ab", null) = "ab" 9579 * StringUtils.wrapIfMissing("ab", "x") = "xabx" 9580 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\"" 9581 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\"" 9582 * StringUtils.wrapIfMissing("ab", "'") = "'ab'" 9583 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'" 9584 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'" 9585 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\"" 9586 * StringUtils.wrapIfMissing("/", "/") = "/" 9587 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/" 9588 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/" 9589 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/" 9590 * </pre> 9591 * 9592 * @param str 9593 * the string to be wrapped, may be {@code null} 9594 * @param wrapWith 9595 * the string that will wrap {@code str} 9596 * @return the wrapped string, or {@code null} if {@code str==null} 9597 * @since 3.5 9598 */ 9599 public static String wrapIfMissing(final String str, final String wrapWith) { 9600 if (isEmpty(str) || isEmpty(wrapWith)) { 9601 return str; 9602 } 9603 9604 final boolean wrapStart = !str.startsWith(wrapWith); 9605 final boolean wrapEnd = !str.endsWith(wrapWith); 9606 if (!wrapStart && !wrapEnd) { 9607 return str; 9608 } 9609 9610 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length()); 9611 if (wrapStart) { 9612 builder.append(wrapWith); 9613 } 9614 builder.append(str); 9615 if (wrapEnd) { 9616 builder.append(wrapWith); 9617 } 9618 return builder.toString(); 9619 } 9620 9621 /** 9622 * <p>{@code StringUtils} instances should NOT be constructed in 9623 * standard programming. Instead, the class should be used as 9624 * {@code StringUtils.trim(" foo ");}.</p> 9625 * 9626 * <p>This constructor is public to permit tools that require a JavaBean 9627 * instance to operate.</p> 9628 */ 9629 public StringUtils() { 9630 super(); 9631 } 9632 9633}