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.Iterator; 025import java.util.List; 026import java.util.Locale; 027import java.util.Objects; 028import java.util.function.Supplier; 029import java.util.regex.Pattern; 030 031/** 032 * <p>Operations on {@link java.lang.String} that are 033 * {@code null} safe.</p> 034 * 035 * <ul> 036 * <li><b>IsEmpty/IsBlank</b> 037 * - checks if a String contains text</li> 038 * <li><b>Trim/Strip</b> 039 * - removes leading and trailing whitespace</li> 040 * <li><b>Equals/Compare</b> 041 * - compares two strings null-safe</li> 042 * <li><b>startsWith</b> 043 * - check if a String starts with a prefix null-safe</li> 044 * <li><b>endsWith</b> 045 * - check if a String ends with a suffix null-safe</li> 046 * <li><b>IndexOf/LastIndexOf/Contains</b> 047 * - null-safe index-of checks 048 * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b> 049 * - index-of any of a set of Strings</li> 050 * <li><b>ContainsOnly/ContainsNone/ContainsAny</b> 051 * - does String contains only/none/any of these characters</li> 052 * <li><b>Substring/Left/Right/Mid</b> 053 * - null-safe substring extractions</li> 054 * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b> 055 * - substring extraction relative to other strings</li> 056 * <li><b>Split/Join</b> 057 * - splits a String into an array of substrings and vice versa</li> 058 * <li><b>Remove/Delete</b> 059 * - removes part of a String</li> 060 * <li><b>Replace/Overlay</b> 061 * - Searches a String and replaces one String with another</li> 062 * <li><b>Chomp/Chop</b> 063 * - removes the last part of a String</li> 064 * <li><b>AppendIfMissing</b> 065 * - appends a suffix to the end of the String if not present</li> 066 * <li><b>PrependIfMissing</b> 067 * - prepends a prefix to the start of the String if not present</li> 068 * <li><b>LeftPad/RightPad/Center/Repeat</b> 069 * - pads a String</li> 070 * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b> 071 * - changes the case of a String</li> 072 * <li><b>CountMatches</b> 073 * - counts the number of occurrences of one String in another</li> 074 * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b> 075 * - checks the characters in a String</li> 076 * <li><b>DefaultString</b> 077 * - protects against a null input String</li> 078 * <li><b>Rotate</b> 079 * - rotate (circular shift) a String</li> 080 * <li><b>Reverse/ReverseDelimited</b> 081 * - reverses a String</li> 082 * <li><b>Abbreviate</b> 083 * - abbreviates a string using ellipsis or another given String</li> 084 * <li><b>Difference</b> 085 * - compares Strings and reports on their differences</li> 086 * <li><b>LevenshteinDistance</b> 087 * - the number of changes needed to change one String into another</li> 088 * </ul> 089 * 090 * <p>The {@code StringUtils} class defines certain words related to 091 * String handling.</p> 092 * 093 * <ul> 094 * <li>null - {@code null}</li> 095 * <li>empty - a zero-length string ({@code ""})</li> 096 * <li>space - the space character ({@code ' '}, char 32)</li> 097 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> 098 * <li>trim - the characters <= 32 as in {@link String#trim()}</li> 099 * </ul> 100 * 101 * <p>{@code StringUtils} handles {@code null} input Strings quietly. 102 * That is to say that a {@code null} input will return {@code null}. 103 * Where a {@code boolean} or {@code int} is being returned 104 * details vary by method.</p> 105 * 106 * <p>A side effect of the {@code null} handling is that a 107 * {@code NullPointerException} should be considered a bug in 108 * {@code StringUtils}.</p> 109 * 110 * <p>Methods in this class give sample code to explain their operation. 111 * The symbol {@code *} is used to indicate any input including {@code null}.</p> 112 * 113 * <p>#ThreadSafe#</p> 114 * @see java.lang.String 115 * @since 1.0 116 */ 117//@Immutable 118public class StringUtils { 119 120 private static final int STRING_BUILDER_SIZE = 256; 121 122 // Performance testing notes (JDK 1.4, Jul03, scolebourne) 123 // Whitespace: 124 // Character.isWhitespace() is faster than WHITESPACE.indexOf() 125 // where WHITESPACE is a string of all whitespace characters 126 // 127 // Character access: 128 // String.charAt(n) versus toCharArray(), then array[n] 129 // String.charAt(n) is about 15% worse for a 10K string 130 // They are about equal for a length 50 string 131 // String.charAt(n) is about 4 times better for a length 3 string 132 // String.charAt(n) is best bet overall 133 // 134 // Append: 135 // String.concat about twice as fast as StringBuffer.append 136 // (not sure who tested this) 137 138 /** 139 * A String for a space character. 140 * 141 * @since 3.2 142 */ 143 public static final String SPACE = " "; 144 145 /** 146 * The empty String {@code ""}. 147 * @since 2.0 148 */ 149 public static final String EMPTY = ""; 150 151 /** 152 * A String for linefeed LF ("\n"). 153 * 154 * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 155 * for Character and String Literals</a> 156 * @since 3.2 157 */ 158 public static final String LF = "\n"; 159 160 /** 161 * A String for carriage return CR ("\r"). 162 * 163 * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 164 * for Character and String Literals</a> 165 * @since 3.2 166 */ 167 public static final String CR = "\r"; 168 169 /** 170 * Represents a failed index search. 171 * @since 2.1 172 */ 173 public static final int INDEX_NOT_FOUND = -1; 174 175 /** 176 * <p>The maximum size to which the padding constant(s) can expand.</p> 177 */ 178 private static final int PAD_LIMIT = 8192; 179 180 // Abbreviating 181 //----------------------------------------------------------------------- 182 /** 183 * <p>Abbreviates a String using ellipses. This will turn 184 * "Now is the time for all good men" into "Now is the time for..."</p> 185 * 186 * <p>Specifically:</p> 187 * <ul> 188 * <li>If the number of characters in {@code str} is less than or equal to 189 * {@code maxWidth}, return {@code str}.</li> 190 * <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li> 191 * <li>If {@code maxWidth} is less than {@code 4}, throw an 192 * {@code IllegalArgumentException}.</li> 193 * <li>In no case will it return a String of length greater than 194 * {@code maxWidth}.</li> 195 * </ul> 196 * 197 * <pre> 198 * StringUtils.abbreviate(null, *) = null 199 * StringUtils.abbreviate("", 4) = "" 200 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 201 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 202 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 203 * StringUtils.abbreviate("abcdefg", 4) = "a..." 204 * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException 205 * </pre> 206 * 207 * @param str the String to check, may be null 208 * @param maxWidth maximum length of result String, must be at least 4 209 * @return abbreviated String, {@code null} if null String input 210 * @throws IllegalArgumentException if the width is too small 211 * @since 2.0 212 */ 213 public static String abbreviate(final String str, final int maxWidth) { 214 return abbreviate(str, "...", 0, maxWidth); 215 } 216 217 /** 218 * <p>Abbreviates a String using ellipses. This will turn 219 * "Now is the time for all good men" into "...is the time for..."</p> 220 * 221 * <p>Works like {@code abbreviate(String, int)}, but allows you to specify 222 * a "left edge" offset. Note that this left edge is not necessarily going to 223 * be the leftmost character in the result, or the first character following the 224 * ellipses, but it will appear somewhere in the result. 225 * 226 * <p>In no case will it return a String of length greater than 227 * {@code maxWidth}.</p> 228 * 229 * <pre> 230 * StringUtils.abbreviate(null, *, *) = null 231 * StringUtils.abbreviate("", 0, 4) = "" 232 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 233 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 234 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 235 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 236 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 237 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 238 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 239 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 240 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 241 * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException 242 * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException 243 * </pre> 244 * 245 * @param str the String to check, may be null 246 * @param offset left edge of source String 247 * @param maxWidth maximum length of result String, must be at least 4 248 * @return abbreviated String, {@code null} if null String input 249 * @throws IllegalArgumentException if the width is too small 250 * @since 2.0 251 */ 252 public static String abbreviate(final String str, final int offset, final int maxWidth) { 253 return abbreviate(str, "...", offset, maxWidth); 254 } 255 256 /** 257 * <p>Abbreviates a String using another given String as replacement marker. This will turn 258 * "Now is the time for all good men" into "Now is the time for..." if "..." was defined 259 * as the replacement marker.</p> 260 * 261 * <p>Specifically:</p> 262 * <ul> 263 * <li>If the number of characters in {@code str} is less than or equal to 264 * {@code maxWidth}, return {@code str}.</li> 265 * <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li> 266 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an 267 * {@code IllegalArgumentException}.</li> 268 * <li>In no case will it return a String of length greater than 269 * {@code maxWidth}.</li> 270 * </ul> 271 * 272 * <pre> 273 * StringUtils.abbreviate(null, "...", *) = null 274 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg" 275 * StringUtils.abbreviate("", "...", 4) = "" 276 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd." 277 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg" 278 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg" 279 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.." 280 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 281 * StringUtils.abbreviate("abcdefg", "..", 2) = IllegalArgumentException 282 * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException 283 * </pre> 284 * 285 * @param str the String to check, may be null 286 * @param abbrevMarker the String used as replacement marker 287 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1} 288 * @return abbreviated String, {@code null} if null String input 289 * @throws IllegalArgumentException if the width is too small 290 * @since 3.6 291 */ 292 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) { 293 return abbreviate(str, abbrevMarker, 0, maxWidth); 294 } 295 /** 296 * <p>Abbreviates a String using a given replacement marker. This will turn 297 * "Now is the time for all good men" into "...is the time for..." if "..." was defined 298 * as the replacement marker.</p> 299 * 300 * <p>Works like {@code abbreviate(String, String, int)}, but allows you to specify 301 * a "left edge" offset. Note that this left edge is not necessarily going to 302 * be the leftmost character in the result, or the first character following the 303 * replacement marker, but it will appear somewhere in the result. 304 * 305 * <p>In no case will it return a String of length greater than {@code maxWidth}.</p> 306 * 307 * <pre> 308 * StringUtils.abbreviate(null, null, *, *) = null 309 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno" 310 * StringUtils.abbreviate("", "...", 0, 4) = "" 311 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---" 312 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi," 313 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi," 314 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi," 315 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::" 316 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..." 317 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno" 318 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno" 319 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno" 320 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = IllegalArgumentException 321 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = IllegalArgumentException 322 * </pre> 323 * 324 * @param str the String to check, may be null 325 * @param abbrevMarker the String used as replacement marker 326 * @param offset left edge of source String 327 * @param maxWidth maximum length of result String, must be at least 4 328 * @return abbreviated String, {@code null} if null String input 329 * @throws IllegalArgumentException if the width is too small 330 * @since 3.6 331 */ 332 public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) { 333 if (isEmpty(str) && isEmpty(abbrevMarker)) { 334 return str; 335 } else if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) { 336 return str.substring(0, maxWidth); 337 } else if (isEmpty(str) || isEmpty(abbrevMarker)) { 338 return str; 339 } 340 final int abbrevMarkerLength = abbrevMarker.length(); 341 final int minAbbrevWidth = abbrevMarkerLength + 1; 342 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1; 343 344 if (maxWidth < minAbbrevWidth) { 345 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth)); 346 } 347 if (str.length() <= maxWidth) { 348 return str; 349 } 350 if (offset > str.length()) { 351 offset = str.length(); 352 } 353 if (str.length() - offset < maxWidth - abbrevMarkerLength) { 354 offset = str.length() - (maxWidth - abbrevMarkerLength); 355 } 356 if (offset <= abbrevMarkerLength+1) { 357 return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker; 358 } 359 if (maxWidth < minAbbrevWidthOffset) { 360 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset)); 361 } 362 if (offset + maxWidth - abbrevMarkerLength < str.length()) { 363 return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength); 364 } 365 return abbrevMarker + str.substring(str.length() - (maxWidth - abbrevMarkerLength)); 366 } 367 368 /** 369 * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied 370 * replacement String.</p> 371 * 372 * <p>This abbreviation only occurs if the following criteria is met:</p> 373 * <ul> 374 * <li>Neither the String for abbreviation nor the replacement String are null or empty </li> 375 * <li>The length to truncate to is less than the length of the supplied String</li> 376 * <li>The length to truncate to is greater than 0</li> 377 * <li>The abbreviated String will have enough room for the length supplied replacement String 378 * and the first and last characters of the supplied String for abbreviation</li> 379 * </ul> 380 * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation. 381 * </p> 382 * 383 * <pre> 384 * StringUtils.abbreviateMiddle(null, null, 0) = null 385 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 386 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 387 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 388 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 389 * </pre> 390 * 391 * @param str the String to abbreviate, may be null 392 * @param middle the String to replace the middle characters with, may be null 393 * @param length the length to abbreviate {@code str} to. 394 * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 395 * @since 2.5 396 */ 397 public static String abbreviateMiddle(final String str, final String middle, final int length) { 398 if (isEmpty(str) || isEmpty(middle)) { 399 return str; 400 } 401 402 if (length >= str.length() || length < middle.length()+2) { 403 return str; 404 } 405 406 final int targetSting = length-middle.length(); 407 final int startOffset = targetSting/2+targetSting%2; 408 final int endOffset = str.length()-targetSting/2; 409 410 return str.substring(0, startOffset) + 411 middle + 412 str.substring(endOffset); 413 } 414 415 /** 416 * Appends the suffix to the end of the string if the string does not 417 * already end with the suffix. 418 * 419 * @param str The string. 420 * @param suffix The suffix to append to the end of the string. 421 * @param ignoreCase Indicates whether the compare should ignore case. 422 * @param suffixes Additional suffixes that are valid terminators (optional). 423 * 424 * @return A new String if suffix was appended, the same string otherwise. 425 */ 426 private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) { 427 if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) { 428 return str; 429 } 430 if (ArrayUtils.isNotEmpty(suffixes)) { 431 for (final CharSequence s : suffixes) { 432 if (endsWith(str, s, ignoreCase)) { 433 return str; 434 } 435 } 436 } 437 return str + suffix.toString(); 438 } 439 440 /** 441 * Appends the suffix to the end of the string if the string does not 442 * already end with any of the suffixes. 443 * 444 * <pre> 445 * StringUtils.appendIfMissing(null, null) = null 446 * StringUtils.appendIfMissing("abc", null) = "abc" 447 * StringUtils.appendIfMissing("", "xyz") = "xyz" 448 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 449 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 450 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 451 * </pre> 452 * <p>With additional suffixes,</p> 453 * <pre> 454 * StringUtils.appendIfMissing(null, null, null) = null 455 * StringUtils.appendIfMissing("abc", null, null) = "abc" 456 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 457 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 458 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 459 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 460 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 461 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 462 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 463 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 464 * </pre> 465 * 466 * @param str The string. 467 * @param suffix The suffix to append to the end of the string. 468 * @param suffixes Additional suffixes that are valid terminators. 469 * 470 * @return A new String if suffix was appended, the same string otherwise. 471 * 472 * @since 3.2 473 */ 474 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 475 return appendIfMissing(str, suffix, false, suffixes); 476 } 477 478 /** 479 * Appends the suffix to the end of the string if the string does not 480 * already end, case insensitive, with any of the suffixes. 481 * 482 * <pre> 483 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 484 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 485 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 486 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 487 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 488 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 489 * </pre> 490 * <p>With additional suffixes,</p> 491 * <pre> 492 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 493 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 494 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 495 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 496 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 497 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "axyz" 498 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 499 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 500 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 501 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 502 * </pre> 503 * 504 * @param str The string. 505 * @param suffix The suffix to append to the end of the string. 506 * @param suffixes Additional suffixes that are valid terminators. 507 * 508 * @return A new String if suffix was appended, the same string otherwise. 509 * 510 * @since 3.2 511 */ 512 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 513 return appendIfMissing(str, suffix, true, suffixes); 514 } 515 516 /** 517 * <p>Capitalizes a String changing the first character to title case as 518 * per {@link Character#toTitleCase(int)}. No other characters are changed.</p> 519 * 520 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}. 521 * A {@code null} input String returns {@code null}.</p> 522 * 523 * <pre> 524 * StringUtils.capitalize(null) = null 525 * StringUtils.capitalize("") = "" 526 * StringUtils.capitalize("cat") = "Cat" 527 * StringUtils.capitalize("cAt") = "CAt" 528 * StringUtils.capitalize("'cat'") = "'cat'" 529 * </pre> 530 * 531 * @param str the String to capitalize, may be null 532 * @return the capitalized String, {@code null} if null String input 533 * @see org.apache.commons.lang3.text.WordUtils#capitalize(String) 534 * @see #uncapitalize(String) 535 * @since 2.0 536 */ 537 public static String capitalize(final String str) { 538 final int strLen = length(str); 539 if (strLen == 0) { 540 return str; 541 } 542 543 final int firstCodepoint = str.codePointAt(0); 544 final int newCodePoint = Character.toTitleCase(firstCodepoint); 545 if (firstCodepoint == newCodePoint) { 546 // already capitalized 547 return str; 548 } 549 550 final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array 551 int outOffset = 0; 552 newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint 553 for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) { 554 final int codepoint = str.codePointAt(inOffset); 555 newCodePoints[outOffset++] = codepoint; // copy the remaining ones 556 inOffset += Character.charCount(codepoint); 557 } 558 return new String(newCodePoints, 0, outOffset); 559 } 560 561 // Centering 562 //----------------------------------------------------------------------- 563 /** 564 * <p>Centers a String in a larger String of size {@code size} 565 * using the space character (' ').</p> 566 * 567 * <p>If the size is less than the String length, the String is returned. 568 * A {@code null} String returns {@code null}. 569 * A negative size is treated as zero.</p> 570 * 571 * <p>Equivalent to {@code center(str, size, " ")}.</p> 572 * 573 * <pre> 574 * StringUtils.center(null, *) = null 575 * StringUtils.center("", 4) = " " 576 * StringUtils.center("ab", -1) = "ab" 577 * StringUtils.center("ab", 4) = " ab " 578 * StringUtils.center("abcd", 2) = "abcd" 579 * StringUtils.center("a", 4) = " a " 580 * </pre> 581 * 582 * @param str the String to center, may be null 583 * @param size the int size of new String, negative treated as zero 584 * @return centered String, {@code null} if null String input 585 */ 586 public static String center(final String str, final int size) { 587 return center(str, size, ' '); 588 } 589 590 /** 591 * <p>Centers a String in a larger String of size {@code size}. 592 * Uses a supplied character as the value to pad the String with.</p> 593 * 594 * <p>If the size is less than the String length, the String is returned. 595 * A {@code null} String returns {@code null}. 596 * A negative size is treated as zero.</p> 597 * 598 * <pre> 599 * StringUtils.center(null, *, *) = null 600 * StringUtils.center("", 4, ' ') = " " 601 * StringUtils.center("ab", -1, ' ') = "ab" 602 * StringUtils.center("ab", 4, ' ') = " ab " 603 * StringUtils.center("abcd", 2, ' ') = "abcd" 604 * StringUtils.center("a", 4, ' ') = " a " 605 * StringUtils.center("a", 4, 'y') = "yayy" 606 * </pre> 607 * 608 * @param str the String to center, may be null 609 * @param size the int size of new String, negative treated as zero 610 * @param padChar the character to pad the new String with 611 * @return centered String, {@code null} if null String input 612 * @since 2.0 613 */ 614 public static String center(String str, final int size, final char padChar) { 615 if (str == null || size <= 0) { 616 return str; 617 } 618 final int strLen = str.length(); 619 final int pads = size - strLen; 620 if (pads <= 0) { 621 return str; 622 } 623 str = leftPad(str, strLen + pads / 2, padChar); 624 str = rightPad(str, size, padChar); 625 return str; 626 } 627 628 /** 629 * <p>Centers a String in a larger String of size {@code size}. 630 * Uses a supplied String as the value to pad the String with.</p> 631 * 632 * <p>If the size is less than the String length, the String is returned. 633 * A {@code null} String returns {@code null}. 634 * A negative size is treated as zero.</p> 635 * 636 * <pre> 637 * StringUtils.center(null, *, *) = null 638 * StringUtils.center("", 4, " ") = " " 639 * StringUtils.center("ab", -1, " ") = "ab" 640 * StringUtils.center("ab", 4, " ") = " ab " 641 * StringUtils.center("abcd", 2, " ") = "abcd" 642 * StringUtils.center("a", 4, " ") = " a " 643 * StringUtils.center("a", 4, "yz") = "yayz" 644 * StringUtils.center("abc", 7, null) = " abc " 645 * StringUtils.center("abc", 7, "") = " abc " 646 * </pre> 647 * 648 * @param str the String to center, may be null 649 * @param size the int size of new String, negative treated as zero 650 * @param padStr the String to pad the new String with, must not be null or empty 651 * @return centered String, {@code null} if null String input 652 * @throws IllegalArgumentException if padStr is {@code null} or empty 653 */ 654 public static String center(String str, final int size, String padStr) { 655 if (str == null || size <= 0) { 656 return str; 657 } 658 if (isEmpty(padStr)) { 659 padStr = SPACE; 660 } 661 final int strLen = str.length(); 662 final int pads = size - strLen; 663 if (pads <= 0) { 664 return str; 665 } 666 str = leftPad(str, strLen + pads / 2, padStr); 667 str = rightPad(str, size, padStr); 668 return str; 669 } 670 671 // Chomping 672 //----------------------------------------------------------------------- 673 /** 674 * <p>Removes one newline from end of a String if it's there, 675 * otherwise leave it alone. A newline is "{@code \n}", 676 * "{@code \r}", or "{@code \r\n}".</p> 677 * 678 * <p>NOTE: This method changed in 2.0. 679 * It now more closely matches Perl chomp.</p> 680 * 681 * <pre> 682 * StringUtils.chomp(null) = null 683 * StringUtils.chomp("") = "" 684 * StringUtils.chomp("abc \r") = "abc " 685 * StringUtils.chomp("abc\n") = "abc" 686 * StringUtils.chomp("abc\r\n") = "abc" 687 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 688 * StringUtils.chomp("abc\n\r") = "abc\n" 689 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 690 * StringUtils.chomp("\r") = "" 691 * StringUtils.chomp("\n") = "" 692 * StringUtils.chomp("\r\n") = "" 693 * </pre> 694 * 695 * @param str the String to chomp a newline from, may be null 696 * @return String without newline, {@code null} if null String input 697 */ 698 public static String chomp(final String str) { 699 if (isEmpty(str)) { 700 return str; 701 } 702 703 if (str.length() == 1) { 704 final char ch = str.charAt(0); 705 if (ch == CharUtils.CR || ch == CharUtils.LF) { 706 return EMPTY; 707 } 708 return str; 709 } 710 711 int lastIdx = str.length() - 1; 712 final char last = str.charAt(lastIdx); 713 714 if (last == CharUtils.LF) { 715 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 716 lastIdx--; 717 } 718 } else if (last != CharUtils.CR) { 719 lastIdx++; 720 } 721 return str.substring(0, lastIdx); 722 } 723 724 /** 725 * <p>Removes {@code separator} from the end of 726 * {@code str} if it's there, otherwise leave it alone.</p> 727 * 728 * <p>NOTE: This method changed in version 2.0. 729 * It now more closely matches Perl chomp. 730 * For the previous behavior, use {@link #substringBeforeLast(String, String)}. 731 * This method uses {@link String#endsWith(String)}.</p> 732 * 733 * <pre> 734 * StringUtils.chomp(null, *) = null 735 * StringUtils.chomp("", *) = "" 736 * StringUtils.chomp("foobar", "bar") = "foo" 737 * StringUtils.chomp("foobar", "baz") = "foobar" 738 * StringUtils.chomp("foo", "foo") = "" 739 * StringUtils.chomp("foo ", "foo") = "foo " 740 * StringUtils.chomp(" foo", "foo") = " " 741 * StringUtils.chomp("foo", "foooo") = "foo" 742 * StringUtils.chomp("foo", "") = "foo" 743 * StringUtils.chomp("foo", null) = "foo" 744 * </pre> 745 * 746 * @param str the String to chomp from, may be null 747 * @param separator separator String, may be null 748 * @return String without trailing separator, {@code null} if null String input 749 * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead 750 */ 751 @Deprecated 752 public static String chomp(final String str, final String separator) { 753 return removeEnd(str, separator); 754 } 755 756 // Chopping 757 //----------------------------------------------------------------------- 758 /** 759 * <p>Remove the last character from a String.</p> 760 * 761 * <p>If the String ends in {@code \r\n}, then remove both 762 * of them.</p> 763 * 764 * <pre> 765 * StringUtils.chop(null) = null 766 * StringUtils.chop("") = "" 767 * StringUtils.chop("abc \r") = "abc " 768 * StringUtils.chop("abc\n") = "abc" 769 * StringUtils.chop("abc\r\n") = "abc" 770 * StringUtils.chop("abc") = "ab" 771 * StringUtils.chop("abc\nabc") = "abc\nab" 772 * StringUtils.chop("a") = "" 773 * StringUtils.chop("\r") = "" 774 * StringUtils.chop("\n") = "" 775 * StringUtils.chop("\r\n") = "" 776 * </pre> 777 * 778 * @param str the String to chop last character from, may be null 779 * @return String without last character, {@code null} if null String input 780 */ 781 public static String chop(final String str) { 782 if (str == null) { 783 return null; 784 } 785 final int strLen = str.length(); 786 if (strLen < 2) { 787 return EMPTY; 788 } 789 final int lastIdx = strLen - 1; 790 final String ret = str.substring(0, lastIdx); 791 final char last = str.charAt(lastIdx); 792 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 793 return ret.substring(0, lastIdx - 1); 794 } 795 return ret; 796 } 797 798 // Compare 799 //----------------------------------------------------------------------- 800 /** 801 * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p> 802 * <ul> 803 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 804 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 805 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 806 * </ul> 807 * 808 * <p>This is a {@code null} safe version of :</p> 809 * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> 810 * 811 * <p>{@code null} value is considered less than non-{@code null} value. 812 * Two {@code null} references are considered equal.</p> 813 * 814 * <pre> 815 * StringUtils.compare(null, null) = 0 816 * StringUtils.compare(null , "a") < 0 817 * StringUtils.compare("a", null) > 0 818 * StringUtils.compare("abc", "abc") = 0 819 * StringUtils.compare("a", "b") < 0 820 * StringUtils.compare("b", "a") > 0 821 * StringUtils.compare("a", "B") > 0 822 * StringUtils.compare("ab", "abc") < 0 823 * </pre> 824 * 825 * @see #compare(String, String, boolean) 826 * @see String#compareTo(String) 827 * @param str1 the String to compare from 828 * @param str2 the String to compare to 829 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2} 830 * @since 3.5 831 */ 832 public static int compare(final String str1, final String str2) { 833 return compare(str1, str2, true); 834 } 835 836 /** 837 * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p> 838 * <ul> 839 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 840 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 841 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 842 * </ul> 843 * 844 * <p>This is a {@code null} safe version of :</p> 845 * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> 846 * 847 * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. 848 * Two {@code null} references are considered equal.</p> 849 * 850 * <pre> 851 * StringUtils.compare(null, null, *) = 0 852 * StringUtils.compare(null , "a", true) < 0 853 * StringUtils.compare(null , "a", false) > 0 854 * StringUtils.compare("a", null, true) > 0 855 * StringUtils.compare("a", null, false) < 0 856 * StringUtils.compare("abc", "abc", *) = 0 857 * StringUtils.compare("a", "b", *) < 0 858 * StringUtils.compare("b", "a", *) > 0 859 * StringUtils.compare("a", "B", *) > 0 860 * StringUtils.compare("ab", "abc", *) < 0 861 * </pre> 862 * 863 * @see String#compareTo(String) 864 * @param str1 the String to compare from 865 * @param str2 the String to compare to 866 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value 867 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2} 868 * @since 3.5 869 */ 870 public static int compare(final String str1, final String str2, final boolean nullIsLess) { 871 if (str1 == str2) { 872 return 0; 873 } 874 if (str1 == null) { 875 return nullIsLess ? -1 : 1; 876 } 877 if (str2 == null) { 878 return nullIsLess ? 1 : - 1; 879 } 880 return str1.compareTo(str2); 881 } 882 883 /** 884 * <p>Compare two Strings lexicographically, ignoring case differences, 885 * as per {@link String#compareToIgnoreCase(String)}, returning :</p> 886 * <ul> 887 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 888 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 889 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 890 * </ul> 891 * 892 * <p>This is a {@code null} safe version of :</p> 893 * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> 894 * 895 * <p>{@code null} value is considered less than non-{@code null} value. 896 * Two {@code null} references are considered equal. 897 * Comparison is case insensitive.</p> 898 * 899 * <pre> 900 * StringUtils.compareIgnoreCase(null, null) = 0 901 * StringUtils.compareIgnoreCase(null , "a") < 0 902 * StringUtils.compareIgnoreCase("a", null) > 0 903 * StringUtils.compareIgnoreCase("abc", "abc") = 0 904 * StringUtils.compareIgnoreCase("abc", "ABC") = 0 905 * StringUtils.compareIgnoreCase("a", "b") < 0 906 * StringUtils.compareIgnoreCase("b", "a") > 0 907 * StringUtils.compareIgnoreCase("a", "B") < 0 908 * StringUtils.compareIgnoreCase("A", "b") < 0 909 * StringUtils.compareIgnoreCase("ab", "ABC") < 0 910 * </pre> 911 * 912 * @see #compareIgnoreCase(String, String, boolean) 913 * @see String#compareToIgnoreCase(String) 914 * @param str1 the String to compare from 915 * @param str2 the String to compare to 916 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, 917 * ignoring case differences. 918 * @since 3.5 919 */ 920 public static int compareIgnoreCase(final String str1, final String str2) { 921 return compareIgnoreCase(str1, str2, true); 922 } 923 924 /** 925 * <p>Compare two Strings lexicographically, ignoring case differences, 926 * as per {@link String#compareToIgnoreCase(String)}, returning :</p> 927 * <ul> 928 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 929 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 930 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 931 * </ul> 932 * 933 * <p>This is a {@code null} safe version of :</p> 934 * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> 935 * 936 * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. 937 * Two {@code null} references are considered equal. 938 * Comparison is case insensitive.</p> 939 * 940 * <pre> 941 * StringUtils.compareIgnoreCase(null, null, *) = 0 942 * StringUtils.compareIgnoreCase(null , "a", true) < 0 943 * StringUtils.compareIgnoreCase(null , "a", false) > 0 944 * StringUtils.compareIgnoreCase("a", null, true) > 0 945 * StringUtils.compareIgnoreCase("a", null, false) < 0 946 * StringUtils.compareIgnoreCase("abc", "abc", *) = 0 947 * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0 948 * StringUtils.compareIgnoreCase("a", "b", *) < 0 949 * StringUtils.compareIgnoreCase("b", "a", *) > 0 950 * StringUtils.compareIgnoreCase("a", "B", *) < 0 951 * StringUtils.compareIgnoreCase("A", "b", *) < 0 952 * StringUtils.compareIgnoreCase("ab", "abc", *) < 0 953 * </pre> 954 * 955 * @see String#compareToIgnoreCase(String) 956 * @param str1 the String to compare from 957 * @param str2 the String to compare to 958 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value 959 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, 960 * ignoring case differences. 961 * @since 3.5 962 */ 963 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { 964 if (str1 == str2) { 965 return 0; 966 } 967 if (str1 == null) { 968 return nullIsLess ? -1 : 1; 969 } 970 if (str2 == null) { 971 return nullIsLess ? 1 : - 1; 972 } 973 return str1.compareToIgnoreCase(str2); 974 } 975 976 /** 977 * <p>Checks if CharSequence contains a search CharSequence, handling {@code null}. 978 * This method uses {@link String#indexOf(String)} if possible.</p> 979 * 980 * <p>A {@code null} CharSequence will return {@code false}.</p> 981 * 982 * <pre> 983 * StringUtils.contains(null, *) = false 984 * StringUtils.contains(*, null) = false 985 * StringUtils.contains("", "") = true 986 * StringUtils.contains("abc", "") = true 987 * StringUtils.contains("abc", "a") = true 988 * StringUtils.contains("abc", "z") = false 989 * </pre> 990 * 991 * @param seq the CharSequence to check, may be null 992 * @param searchSeq the CharSequence to find, may be null 993 * @return true if the CharSequence contains the search CharSequence, 994 * false if not or {@code null} string input 995 * @since 2.0 996 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 997 */ 998 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 999 if (seq == null || searchSeq == null) { 1000 return false; 1001 } 1002 return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0; 1003 } 1004 1005 // Contains 1006 //----------------------------------------------------------------------- 1007 /** 1008 * <p>Checks if CharSequence contains a search character, handling {@code null}. 1009 * This method uses {@link String#indexOf(int)} if possible.</p> 1010 * 1011 * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p> 1012 * 1013 * <pre> 1014 * StringUtils.contains(null, *) = false 1015 * StringUtils.contains("", *) = false 1016 * StringUtils.contains("abc", 'a') = true 1017 * StringUtils.contains("abc", 'z') = false 1018 * </pre> 1019 * 1020 * @param seq the CharSequence to check, may be null 1021 * @param searchChar the character to find 1022 * @return true if the CharSequence contains the search character, 1023 * false if not or {@code null} string input 1024 * @since 2.0 1025 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1026 */ 1027 public static boolean contains(final CharSequence seq, final int searchChar) { 1028 if (isEmpty(seq)) { 1029 return false; 1030 } 1031 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1032 } 1033 1034 // ContainsAny 1035 //----------------------------------------------------------------------- 1036 /** 1037 * <p>Checks if the CharSequence contains any character in the given 1038 * set of characters.</p> 1039 * 1040 * <p>A {@code null} CharSequence will return {@code false}. 1041 * A {@code null} or zero length search array will return {@code false}.</p> 1042 * 1043 * <pre> 1044 * StringUtils.containsAny(null, *) = false 1045 * StringUtils.containsAny("", *) = false 1046 * StringUtils.containsAny(*, null) = false 1047 * StringUtils.containsAny(*, []) = false 1048 * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true 1049 * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true 1050 * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true 1051 * StringUtils.containsAny("aba", ['z']) = false 1052 * </pre> 1053 * 1054 * @param cs the CharSequence to check, may be null 1055 * @param searchChars the chars to search for, may be null 1056 * @return the {@code true} if any of the chars are found, 1057 * {@code false} if no match or null input 1058 * @since 2.4 1059 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1060 */ 1061 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1062 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1063 return false; 1064 } 1065 final int csLength = cs.length(); 1066 final int searchLength = searchChars.length; 1067 final int csLast = csLength - 1; 1068 final int searchLast = searchLength - 1; 1069 for (int i = 0; i < csLength; i++) { 1070 final char ch = cs.charAt(i); 1071 for (int j = 0; j < searchLength; j++) { 1072 if (searchChars[j] == ch) { 1073 if (Character.isHighSurrogate(ch)) { 1074 if (j == searchLast) { 1075 // missing low surrogate, fine, like String.indexOf(String) 1076 return true; 1077 } 1078 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1079 return true; 1080 } 1081 } else { 1082 // ch is in the Basic Multilingual Plane 1083 return true; 1084 } 1085 } 1086 } 1087 } 1088 return false; 1089 } 1090 1091 /** 1092 * <p> 1093 * Checks if the CharSequence contains any character in the given set of characters. 1094 * </p> 1095 * 1096 * <p> 1097 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return 1098 * {@code false}. 1099 * </p> 1100 * 1101 * <pre> 1102 * StringUtils.containsAny(null, *) = false 1103 * StringUtils.containsAny("", *) = false 1104 * StringUtils.containsAny(*, null) = false 1105 * StringUtils.containsAny(*, "") = false 1106 * StringUtils.containsAny("zzabyycdxx", "za") = true 1107 * StringUtils.containsAny("zzabyycdxx", "by") = true 1108 * StringUtils.containsAny("zzabyycdxx", "zy") = true 1109 * StringUtils.containsAny("zzabyycdxx", "\tx") = true 1110 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true 1111 * StringUtils.containsAny("aba", "z") = false 1112 * </pre> 1113 * 1114 * @param cs 1115 * the CharSequence to check, may be null 1116 * @param searchChars 1117 * the chars to search for, may be null 1118 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input 1119 * @since 2.4 1120 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1121 */ 1122 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1123 if (searchChars == null) { 1124 return false; 1125 } 1126 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1127 } 1128 1129 /** 1130 * <p>Checks if the CharSequence contains any of the CharSequences in the given array.</p> 1131 * 1132 * <p> 1133 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero 1134 * length search array will return {@code false}. 1135 * </p> 1136 * 1137 * <pre> 1138 * StringUtils.containsAny(null, *) = false 1139 * StringUtils.containsAny("", *) = false 1140 * StringUtils.containsAny(*, null) = false 1141 * StringUtils.containsAny(*, []) = false 1142 * StringUtils.containsAny("abcd", "ab", null) = true 1143 * StringUtils.containsAny("abcd", "ab", "cd") = true 1144 * StringUtils.containsAny("abc", "d", "abc") = true 1145 * </pre> 1146 * 1147 * 1148 * @param cs The CharSequence to check, may be null 1149 * @param searchCharSequences The array of CharSequences to search for, may be null. 1150 * Individual CharSequences may be null as well. 1151 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1152 * @since 3.4 1153 */ 1154 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) { 1155 if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) { 1156 return false; 1157 } 1158 for (final CharSequence searchCharSequence : searchCharSequences) { 1159 if (contains(cs, searchCharSequence)) { 1160 return true; 1161 } 1162 } 1163 return false; 1164 } 1165 1166 /** 1167 * <p>Checks if CharSequence contains a search CharSequence irrespective of case, 1168 * handling {@code null}. Case-insensitivity is defined as by 1169 * {@link String#equalsIgnoreCase(String)}. 1170 * 1171 * <p>A {@code null} CharSequence will return {@code false}.</p> 1172 * 1173 * <pre> 1174 * StringUtils.containsIgnoreCase(null, *) = false 1175 * StringUtils.containsIgnoreCase(*, null) = false 1176 * StringUtils.containsIgnoreCase("", "") = true 1177 * StringUtils.containsIgnoreCase("abc", "") = true 1178 * StringUtils.containsIgnoreCase("abc", "a") = true 1179 * StringUtils.containsIgnoreCase("abc", "z") = false 1180 * StringUtils.containsIgnoreCase("abc", "A") = true 1181 * StringUtils.containsIgnoreCase("abc", "Z") = false 1182 * </pre> 1183 * 1184 * @param str the CharSequence to check, may be null 1185 * @param searchStr the CharSequence to find, may be null 1186 * @return true if the CharSequence contains the search CharSequence irrespective of 1187 * case or false if not or {@code null} string input 1188 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence) 1189 */ 1190 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1191 if (str == null || searchStr == null) { 1192 return false; 1193 } 1194 final int len = searchStr.length(); 1195 final int max = str.length() - len; 1196 for (int i = 0; i <= max; i++) { 1197 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) { 1198 return true; 1199 } 1200 } 1201 return false; 1202 } 1203 1204 // ContainsNone 1205 //----------------------------------------------------------------------- 1206 /** 1207 * <p>Checks that the CharSequence does not contain certain characters.</p> 1208 * 1209 * <p>A {@code null} CharSequence will return {@code true}. 1210 * A {@code null} invalid character array will return {@code true}. 1211 * An empty CharSequence (length()=0) always returns true.</p> 1212 * 1213 * <pre> 1214 * StringUtils.containsNone(null, *) = true 1215 * StringUtils.containsNone(*, null) = true 1216 * StringUtils.containsNone("", *) = true 1217 * StringUtils.containsNone("ab", '') = true 1218 * StringUtils.containsNone("abab", 'xyz') = true 1219 * StringUtils.containsNone("ab1", 'xyz') = true 1220 * StringUtils.containsNone("abz", 'xyz') = false 1221 * </pre> 1222 * 1223 * @param cs the CharSequence to check, may be null 1224 * @param searchChars an array of invalid chars, may be null 1225 * @return true if it contains none of the invalid chars, or is null 1226 * @since 2.0 1227 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1228 */ 1229 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1230 if (cs == null || searchChars == null) { 1231 return true; 1232 } 1233 final int csLen = cs.length(); 1234 final int csLast = csLen - 1; 1235 final int searchLen = searchChars.length; 1236 final int searchLast = searchLen - 1; 1237 for (int i = 0; i < csLen; i++) { 1238 final char ch = cs.charAt(i); 1239 for (int j = 0; j < searchLen; j++) { 1240 if (searchChars[j] == ch) { 1241 if (Character.isHighSurrogate(ch)) { 1242 if (j == searchLast) { 1243 // missing low surrogate, fine, like String.indexOf(String) 1244 return false; 1245 } 1246 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1247 return false; 1248 } 1249 } else { 1250 // ch is in the Basic Multilingual Plane 1251 return false; 1252 } 1253 } 1254 } 1255 } 1256 return true; 1257 } 1258 1259 /** 1260 * <p>Checks that the CharSequence does not contain certain characters.</p> 1261 * 1262 * <p>A {@code null} CharSequence will return {@code true}. 1263 * A {@code null} invalid character array will return {@code true}. 1264 * An empty String ("") always returns true.</p> 1265 * 1266 * <pre> 1267 * StringUtils.containsNone(null, *) = true 1268 * StringUtils.containsNone(*, null) = true 1269 * StringUtils.containsNone("", *) = true 1270 * StringUtils.containsNone("ab", "") = true 1271 * StringUtils.containsNone("abab", "xyz") = true 1272 * StringUtils.containsNone("ab1", "xyz") = true 1273 * StringUtils.containsNone("abz", "xyz") = false 1274 * </pre> 1275 * 1276 * @param cs the CharSequence to check, may be null 1277 * @param invalidChars a String of invalid chars, may be null 1278 * @return true if it contains none of the invalid chars, or is null 1279 * @since 2.0 1280 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1281 */ 1282 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1283 if (cs == null || invalidChars == null) { 1284 return true; 1285 } 1286 return containsNone(cs, invalidChars.toCharArray()); 1287 } 1288 1289 // ContainsOnly 1290 //----------------------------------------------------------------------- 1291 /** 1292 * <p>Checks if the CharSequence contains only certain characters.</p> 1293 * 1294 * <p>A {@code null} CharSequence will return {@code false}. 1295 * A {@code null} valid character array will return {@code false}. 1296 * An empty CharSequence (length()=0) always returns {@code true}.</p> 1297 * 1298 * <pre> 1299 * StringUtils.containsOnly(null, *) = false 1300 * StringUtils.containsOnly(*, null) = false 1301 * StringUtils.containsOnly("", *) = true 1302 * StringUtils.containsOnly("ab", '') = false 1303 * StringUtils.containsOnly("abab", 'abc') = true 1304 * StringUtils.containsOnly("ab1", 'abc') = false 1305 * StringUtils.containsOnly("abz", 'abc') = false 1306 * </pre> 1307 * 1308 * @param cs the String to check, may be null 1309 * @param valid an array of valid chars, may be null 1310 * @return true if it only contains valid chars and is non-null 1311 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1312 */ 1313 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1314 // All these pre-checks are to maintain API with an older version 1315 if (valid == null || cs == null) { 1316 return false; 1317 } 1318 if (cs.length() == 0) { 1319 return true; 1320 } 1321 if (valid.length == 0) { 1322 return false; 1323 } 1324 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1325 } 1326 1327 /** 1328 * <p>Checks if the CharSequence contains only certain characters.</p> 1329 * 1330 * <p>A {@code null} CharSequence will return {@code false}. 1331 * A {@code null} valid character String will return {@code false}. 1332 * An empty String (length()=0) always returns {@code true}.</p> 1333 * 1334 * <pre> 1335 * StringUtils.containsOnly(null, *) = false 1336 * StringUtils.containsOnly(*, null) = false 1337 * StringUtils.containsOnly("", *) = true 1338 * StringUtils.containsOnly("ab", "") = false 1339 * StringUtils.containsOnly("abab", "abc") = true 1340 * StringUtils.containsOnly("ab1", "abc") = false 1341 * StringUtils.containsOnly("abz", "abc") = false 1342 * </pre> 1343 * 1344 * @param cs the CharSequence to check, may be null 1345 * @param validChars a String of valid chars, may be null 1346 * @return true if it only contains valid chars and is non-null 1347 * @since 2.0 1348 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1349 */ 1350 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1351 if (cs == null || validChars == null) { 1352 return false; 1353 } 1354 return containsOnly(cs, validChars.toCharArray()); 1355 } 1356 1357 /** 1358 * <p>Check whether the given CharSequence contains any whitespace characters.</p> 1359 * 1360 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1361 * 1362 * @param seq the CharSequence to check (may be {@code null}) 1363 * @return {@code true} if the CharSequence is not empty and 1364 * contains at least 1 (breaking) whitespace character 1365 * @since 3.0 1366 */ 1367 // From org.springframework.util.StringUtils, under Apache License 2.0 1368 public static boolean containsWhitespace(final CharSequence seq) { 1369 if (isEmpty(seq)) { 1370 return false; 1371 } 1372 final int strLen = seq.length(); 1373 for (int i = 0; i < strLen; i++) { 1374 if (Character.isWhitespace(seq.charAt(i))) { 1375 return true; 1376 } 1377 } 1378 return false; 1379 } 1380 1381 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) { 1382 for (int i = 0; i < decomposed.length(); i++) { 1383 if (decomposed.charAt(i) == '\u0141') { 1384 decomposed.deleteCharAt(i); 1385 decomposed.insert(i, 'L'); 1386 } else if (decomposed.charAt(i) == '\u0142') { 1387 decomposed.deleteCharAt(i); 1388 decomposed.insert(i, 'l'); 1389 } 1390 } 1391 } 1392 1393 /** 1394 * <p>Counts how many times the char appears in the given string.</p> 1395 * 1396 * <p>A {@code null} or empty ("") String input returns {@code 0}.</p> 1397 * 1398 * <pre> 1399 * StringUtils.countMatches(null, *) = 0 1400 * StringUtils.countMatches("", *) = 0 1401 * StringUtils.countMatches("abba", 0) = 0 1402 * StringUtils.countMatches("abba", 'a') = 2 1403 * StringUtils.countMatches("abba", 'b') = 2 1404 * StringUtils.countMatches("abba", 'x') = 0 1405 * </pre> 1406 * 1407 * @param str the CharSequence to check, may be null 1408 * @param ch the char to count 1409 * @return the number of occurrences, 0 if the CharSequence is {@code null} 1410 * @since 3.4 1411 */ 1412 public static int countMatches(final CharSequence str, final char ch) { 1413 if (isEmpty(str)) { 1414 return 0; 1415 } 1416 int count = 0; 1417 // We could also call str.toCharArray() for faster look ups but that would generate more garbage. 1418 for (int i = 0; i < str.length(); i++) { 1419 if (ch == str.charAt(i)) { 1420 count++; 1421 } 1422 } 1423 return count; 1424 } 1425 1426 // Count matches 1427 //----------------------------------------------------------------------- 1428 /** 1429 * <p>Counts how many times the substring appears in the larger string.</p> 1430 * 1431 * <p>A {@code null} or empty ("") String input returns {@code 0}.</p> 1432 * 1433 * <pre> 1434 * StringUtils.countMatches(null, *) = 0 1435 * StringUtils.countMatches("", *) = 0 1436 * StringUtils.countMatches("abba", null) = 0 1437 * StringUtils.countMatches("abba", "") = 0 1438 * StringUtils.countMatches("abba", "a") = 2 1439 * StringUtils.countMatches("abba", "ab") = 1 1440 * StringUtils.countMatches("abba", "xxx") = 0 1441 * </pre> 1442 * 1443 * @param str the CharSequence to check, may be null 1444 * @param sub the substring to count, may be null 1445 * @return the number of occurrences, 0 if either CharSequence is {@code null} 1446 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 1447 */ 1448 public static int countMatches(final CharSequence str, final CharSequence sub) { 1449 if (isEmpty(str) || isEmpty(sub)) { 1450 return 0; 1451 } 1452 int count = 0; 1453 int idx = 0; 1454 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 1455 count++; 1456 idx += sub.length(); 1457 } 1458 return count; 1459 } 1460 1461 /** 1462 * <p>Returns either the passed in CharSequence, or if the CharSequence is 1463 * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.</p> 1464 * 1465 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1466 * 1467 * <pre> 1468 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 1469 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 1470 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 1471 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 1472 * StringUtils.defaultIfBlank("", null) = null 1473 * </pre> 1474 * @param <T> the specific kind of CharSequence 1475 * @param str the CharSequence to check, may be null 1476 * @param defaultStr the default CharSequence to return 1477 * if the input is whitespace, empty ("") or {@code null}, may be null 1478 * @return the passed in CharSequence, or the default 1479 * @see StringUtils#defaultString(String, String) 1480 */ 1481 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 1482 return isBlank(str) ? defaultStr : str; 1483 } 1484 1485 /** 1486 * <p>Returns either the passed in CharSequence, or if the CharSequence is 1487 * empty or {@code null}, the value of {@code defaultStr}.</p> 1488 * 1489 * <pre> 1490 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 1491 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 1492 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 1493 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 1494 * StringUtils.defaultIfEmpty("", null) = null 1495 * </pre> 1496 * @param <T> the specific kind of CharSequence 1497 * @param str the CharSequence to check, may be null 1498 * @param defaultStr the default CharSequence to return 1499 * if the input is empty ("") or {@code null}, may be null 1500 * @return the passed in CharSequence, or the default 1501 * @see StringUtils#defaultString(String, String) 1502 */ 1503 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 1504 return isEmpty(str) ? defaultStr : str; 1505 } 1506 1507 /** 1508 * <p>Returns either the passed in String, 1509 * or if the String is {@code null}, an empty String ("").</p> 1510 * 1511 * <pre> 1512 * StringUtils.defaultString(null) = "" 1513 * StringUtils.defaultString("") = "" 1514 * StringUtils.defaultString("bat") = "bat" 1515 * </pre> 1516 * 1517 * @see ObjectUtils#toString(Object) 1518 * @see String#valueOf(Object) 1519 * @param str the String to check, may be null 1520 * @return the passed in String, or the empty String if it 1521 * was {@code null} 1522 */ 1523 public static String defaultString(final String str) { 1524 return defaultString(str, EMPTY); 1525 } 1526 1527 /** 1528 * <p>Returns either the passed in String, or if the String is 1529 * {@code null}, the value of {@code defaultStr}.</p> 1530 * 1531 * <pre> 1532 * StringUtils.defaultString(null, "NULL") = "NULL" 1533 * StringUtils.defaultString("", "NULL") = "" 1534 * StringUtils.defaultString("bat", "NULL") = "bat" 1535 * </pre> 1536 * 1537 * @see ObjectUtils#toString(Object,String) 1538 * @see String#valueOf(Object) 1539 * @param str the String to check, may be null 1540 * @param defaultStr the default String to return 1541 * if the input is {@code null}, may be null 1542 * @return the passed in String, or the default if it was {@code null} 1543 */ 1544 public static String defaultString(final String str, final String defaultStr) { 1545 return str == null ? defaultStr : str; 1546 } 1547 1548 // Delete 1549 //----------------------------------------------------------------------- 1550 /** 1551 * <p>Deletes all whitespaces from a String as defined by 1552 * {@link Character#isWhitespace(char)}.</p> 1553 * 1554 * <pre> 1555 * StringUtils.deleteWhitespace(null) = null 1556 * StringUtils.deleteWhitespace("") = "" 1557 * StringUtils.deleteWhitespace("abc") = "abc" 1558 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1559 * </pre> 1560 * 1561 * @param str the String to delete whitespace from, may be null 1562 * @return the String without whitespaces, {@code null} if null String input 1563 */ 1564 public static String deleteWhitespace(final String str) { 1565 if (isEmpty(str)) { 1566 return str; 1567 } 1568 final int sz = str.length(); 1569 final char[] chs = new char[sz]; 1570 int count = 0; 1571 for (int i = 0; i < sz; i++) { 1572 if (!Character.isWhitespace(str.charAt(i))) { 1573 chs[count++] = str.charAt(i); 1574 } 1575 } 1576 if (count == sz) { 1577 return str; 1578 } 1579 return new String(chs, 0, count); 1580 } 1581 1582 // Difference 1583 //----------------------------------------------------------------------- 1584 /** 1585 * <p>Compares two Strings, and returns the portion where they differ. 1586 * More precisely, return the remainder of the second String, 1587 * starting from where it's different from the first. This means that 1588 * the difference between "abc" and "ab" is the empty String and not "c". </p> 1589 * 1590 * <p>For example, 1591 * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p> 1592 * 1593 * <pre> 1594 * StringUtils.difference(null, null) = null 1595 * StringUtils.difference("", "") = "" 1596 * StringUtils.difference("", "abc") = "abc" 1597 * StringUtils.difference("abc", "") = "" 1598 * StringUtils.difference("abc", "abc") = "" 1599 * StringUtils.difference("abc", "ab") = "" 1600 * StringUtils.difference("ab", "abxyz") = "xyz" 1601 * StringUtils.difference("abcde", "abxyz") = "xyz" 1602 * StringUtils.difference("abcde", "xyz") = "xyz" 1603 * </pre> 1604 * 1605 * @param str1 the first String, may be null 1606 * @param str2 the second String, may be null 1607 * @return the portion of str2 where it differs from str1; returns the 1608 * empty String if they are equal 1609 * @see #indexOfDifference(CharSequence,CharSequence) 1610 * @since 2.0 1611 */ 1612 public static String difference(final String str1, final String str2) { 1613 if (str1 == null) { 1614 return str2; 1615 } 1616 if (str2 == null) { 1617 return str1; 1618 } 1619 final int at = indexOfDifference(str1, str2); 1620 if (at == INDEX_NOT_FOUND) { 1621 return EMPTY; 1622 } 1623 return str2.substring(at); 1624 } 1625 1626 /** 1627 * <p>Check if a CharSequence ends with a specified suffix.</p> 1628 * 1629 * <p>{@code null}s are handled without exceptions. Two {@code null} 1630 * references are considered to be equal. The comparison is case sensitive.</p> 1631 * 1632 * <pre> 1633 * StringUtils.endsWith(null, null) = true 1634 * StringUtils.endsWith(null, "def") = false 1635 * StringUtils.endsWith("abcdef", null) = false 1636 * StringUtils.endsWith("abcdef", "def") = true 1637 * StringUtils.endsWith("ABCDEF", "def") = false 1638 * StringUtils.endsWith("ABCDEF", "cde") = false 1639 * StringUtils.endsWith("ABCDEF", "") = true 1640 * </pre> 1641 * 1642 * @see java.lang.String#endsWith(String) 1643 * @param str the CharSequence to check, may be null 1644 * @param suffix the suffix to find, may be null 1645 * @return {@code true} if the CharSequence ends with the suffix, case sensitive, or 1646 * both {@code null} 1647 * @since 2.4 1648 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1649 */ 1650 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1651 return endsWith(str, suffix, false); 1652 } 1653 1654 /** 1655 * <p>Check if a CharSequence ends with a specified suffix (optionally case insensitive).</p> 1656 * 1657 * @see java.lang.String#endsWith(String) 1658 * @param str the CharSequence to check, may be null 1659 * @param suffix the suffix to find, may be null 1660 * @param ignoreCase indicates whether the compare should ignore case 1661 * (case insensitive) or not. 1662 * @return {@code true} if the CharSequence starts with the prefix or 1663 * both {@code null} 1664 */ 1665 private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) { 1666 if (str == null || suffix == null) { 1667 return str == suffix; 1668 } 1669 if (suffix.length() > str.length()) { 1670 return false; 1671 } 1672 final int strOffset = str.length() - suffix.length(); 1673 return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length()); 1674 } 1675 1676 /** 1677 * <p>Check if a CharSequence ends with any of the provided case-sensitive suffixes.</p> 1678 * 1679 * <pre> 1680 * StringUtils.endsWithAny(null, null) = false 1681 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1682 * StringUtils.endsWithAny("abcxyz", null) = false 1683 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1684 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1685 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1686 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1687 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1688 * </pre> 1689 * 1690 * @param sequence the CharSequence to check, may be null 1691 * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null} 1692 * @see StringUtils#endsWith(CharSequence, CharSequence) 1693 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or 1694 * the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}. 1695 * @since 3.0 1696 */ 1697 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1698 if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { 1699 return false; 1700 } 1701 for (final CharSequence searchString : searchStrings) { 1702 if (endsWith(sequence, searchString)) { 1703 return true; 1704 } 1705 } 1706 return false; 1707 } 1708 1709 /** 1710 * <p>Case insensitive check if a CharSequence ends with a specified suffix.</p> 1711 * 1712 * <p>{@code null}s are handled without exceptions. Two {@code null} 1713 * references are considered to be equal. The comparison is case insensitive.</p> 1714 * 1715 * <pre> 1716 * StringUtils.endsWithIgnoreCase(null, null) = true 1717 * StringUtils.endsWithIgnoreCase(null, "def") = false 1718 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1719 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1720 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1721 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1722 * </pre> 1723 * 1724 * @see java.lang.String#endsWith(String) 1725 * @param str the CharSequence to check, may be null 1726 * @param suffix the suffix to find, may be null 1727 * @return {@code true} if the CharSequence ends with the suffix, case insensitive, or 1728 * both {@code null} 1729 * @since 2.4 1730 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1731 */ 1732 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1733 return endsWith(str, suffix, true); 1734 } 1735 1736 // Equals 1737 //----------------------------------------------------------------------- 1738 /** 1739 * <p>Compares two CharSequences, returning {@code true} if they represent 1740 * equal sequences of characters.</p> 1741 * 1742 * <p>{@code null}s are handled without exceptions. Two {@code null} 1743 * references are considered to be equal. The comparison is <strong>case sensitive</strong>.</p> 1744 * 1745 * <pre> 1746 * StringUtils.equals(null, null) = true 1747 * StringUtils.equals(null, "abc") = false 1748 * StringUtils.equals("abc", null) = false 1749 * StringUtils.equals("abc", "abc") = true 1750 * StringUtils.equals("abc", "ABC") = false 1751 * </pre> 1752 * 1753 * @param cs1 the first CharSequence, may be {@code null} 1754 * @param cs2 the second CharSequence, may be {@code null} 1755 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} 1756 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1757 * @see Object#equals(Object) 1758 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1759 */ 1760 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1761 if (cs1 == cs2) { 1762 return true; 1763 } 1764 if (cs1 == null || cs2 == null) { 1765 return false; 1766 } 1767 if (cs1.length() != cs2.length()) { 1768 return false; 1769 } 1770 if (cs1 instanceof String && cs2 instanceof String) { 1771 return cs1.equals(cs2); 1772 } 1773 // Step-wise comparison 1774 final int length = cs1.length(); 1775 for (int i = 0; i < length; i++) { 1776 if (cs1.charAt(i) != cs2.charAt(i)) { 1777 return false; 1778 } 1779 } 1780 return true; 1781 } 1782 1783 /** 1784 * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1785 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}.</p> 1786 * 1787 * <pre> 1788 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1789 * StringUtils.equalsAny(null, null, null) = true 1790 * StringUtils.equalsAny(null, "abc", "def") = false 1791 * StringUtils.equalsAny("abc", null, "def") = false 1792 * StringUtils.equalsAny("abc", "abc", "def") = true 1793 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1794 * </pre> 1795 * 1796 * @param string to compare, may be {@code null}. 1797 * @param searchStrings a vararg of strings, may be {@code null}. 1798 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; 1799 * {@code false} if {@code searchStrings} is null or contains no matches. 1800 * @since 3.5 1801 */ 1802 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1803 if (ArrayUtils.isNotEmpty(searchStrings)) { 1804 for (final CharSequence next : searchStrings) { 1805 if (equals(string, next)) { 1806 return true; 1807 } 1808 } 1809 } 1810 return false; 1811 } 1812 1813 /** 1814 * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1815 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.</p> 1816 * 1817 * <pre> 1818 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1819 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1820 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1821 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1822 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1823 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 1824 * </pre> 1825 * 1826 * @param string to compare, may be {@code null}. 1827 * @param searchStrings a vararg of strings, may be {@code null}. 1828 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings}; 1829 * {@code false} if {@code searchStrings} is null or contains no matches. 1830 * @since 3.5 1831 */ 1832 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) { 1833 if (ArrayUtils.isNotEmpty(searchStrings)) { 1834 for (final CharSequence next : searchStrings) { 1835 if (equalsIgnoreCase(string, next)) { 1836 return true; 1837 } 1838 } 1839 } 1840 return false; 1841 } 1842 1843 /** 1844 * <p>Compares two CharSequences, returning {@code true} if they represent 1845 * equal sequences of characters, ignoring case.</p> 1846 * 1847 * <p>{@code null}s are handled without exceptions. Two {@code null} 1848 * references are considered equal. The comparison is <strong>case insensitive</strong>.</p> 1849 * 1850 * <pre> 1851 * StringUtils.equalsIgnoreCase(null, null) = true 1852 * StringUtils.equalsIgnoreCase(null, "abc") = false 1853 * StringUtils.equalsIgnoreCase("abc", null) = false 1854 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1855 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1856 * </pre> 1857 * 1858 * @param cs1 the first CharSequence, may be {@code null} 1859 * @param cs2 the second CharSequence, may be {@code null} 1860 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null} 1861 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1862 * @see #equals(CharSequence, CharSequence) 1863 */ 1864 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1865 if (cs1 == cs2) { 1866 return true; 1867 } 1868 if (cs1 == null || cs2 == null) { 1869 return false; 1870 } 1871 if (cs1.length() != cs2.length()) { 1872 return false; 1873 } 1874 return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length()); 1875 } 1876 1877 /** 1878 * <p>Returns the first value in the array which is not empty (""), 1879 * {@code null} or whitespace only.</p> 1880 * 1881 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1882 * 1883 * <p>If all values are blank or the array is {@code null} 1884 * or empty then {@code null} is returned.</p> 1885 * 1886 * <pre> 1887 * StringUtils.firstNonBlank(null, null, null) = null 1888 * StringUtils.firstNonBlank(null, "", " ") = null 1889 * StringUtils.firstNonBlank("abc") = "abc" 1890 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1891 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1892 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1893 * StringUtils.firstNonBlank() = null 1894 * </pre> 1895 * 1896 * @param <T> the specific kind of CharSequence 1897 * @param values the values to test, may be {@code null} or empty 1898 * @return the first value from {@code values} which is not blank, 1899 * or {@code null} if there are no non-blank values 1900 * @since 3.8 1901 */ 1902 @SafeVarargs 1903 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1904 if (values != null) { 1905 for (final T val : values) { 1906 if (isNotBlank(val)) { 1907 return val; 1908 } 1909 } 1910 } 1911 return null; 1912 } 1913 1914 /** 1915 * <p>Returns the first value in the array which is not empty.</p> 1916 * 1917 * <p>If all values are empty or the array is {@code null} 1918 * or empty then {@code null} is returned.</p> 1919 * 1920 * <pre> 1921 * StringUtils.firstNonEmpty(null, null, null) = null 1922 * StringUtils.firstNonEmpty(null, null, "") = null 1923 * StringUtils.firstNonEmpty(null, "", " ") = " " 1924 * StringUtils.firstNonEmpty("abc") = "abc" 1925 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1926 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1927 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1928 * StringUtils.firstNonEmpty() = null 1929 * </pre> 1930 * 1931 * @param <T> the specific kind of CharSequence 1932 * @param values the values to test, may be {@code null} or empty 1933 * @return the first value from {@code values} which is not empty, 1934 * or {@code null} if there are no non-empty values 1935 * @since 3.8 1936 */ 1937 @SafeVarargs 1938 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 1939 if (values != null) { 1940 for (final T val : values) { 1941 if (isNotEmpty(val)) { 1942 return val; 1943 } 1944 } 1945 } 1946 return null; 1947 } 1948 1949 /** 1950 * Calls {@link String#getBytes(Charset)} in a null-safe manner. 1951 * 1952 * @param string input string 1953 * @param charset The {@link Charset} to encode the {@code String}. If null, then use the default Charset. 1954 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 1955 * @see String#getBytes(Charset) 1956 * @since 3.10 1957 */ 1958 public static byte[] getBytes(final String string, final Charset charset) { 1959 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 1960 } 1961 1962 /** 1963 * Calls {@link String#getBytes(String)} in a null-safe manner. 1964 * 1965 * @param string input string 1966 * @param charset The {@link Charset} name to encode the {@code String}. If null, then use the default Charset. 1967 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 1968 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 1969 * @see String#getBytes(String) 1970 * @since 3.10 1971 */ 1972 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 1973 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 1974 } 1975 1976 /** 1977 * <p>Compares all Strings in an array and returns the initial sequence of 1978 * characters that is common to all of them.</p> 1979 * 1980 * <p>For example, 1981 * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "}</p> 1982 * 1983 * <pre> 1984 * StringUtils.getCommonPrefix(null) = "" 1985 * StringUtils.getCommonPrefix(new String[] {}) = "" 1986 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 1987 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 1988 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 1989 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 1990 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 1991 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 1992 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 1993 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 1994 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 1995 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 1996 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 1997 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 1998 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 1999 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 2000 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 2001 * </pre> 2002 * 2003 * @param strs array of String objects, entries may be null 2004 * @return the initial sequence of characters that are common to all Strings 2005 * in the array; empty String if the array is null, the elements are all null 2006 * or if there is no common prefix. 2007 * @since 2.4 2008 */ 2009 public static String getCommonPrefix(final String... strs) { 2010 if (ArrayUtils.isEmpty(strs)) { 2011 return EMPTY; 2012 } 2013 final int smallestIndexOfDiff = indexOfDifference(strs); 2014 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2015 // all strings were identical 2016 if (strs[0] == null) { 2017 return EMPTY; 2018 } 2019 return strs[0]; 2020 } else if (smallestIndexOfDiff == 0) { 2021 // there were no common initial characters 2022 return EMPTY; 2023 } else { 2024 // we found a common initial character sequence 2025 return strs[0].substring(0, smallestIndexOfDiff); 2026 } 2027 } 2028 2029 /** 2030 * <p>Checks if a String {@code str} contains Unicode digits, 2031 * if yes then concatenate all the digits in {@code str} and return it as a String.</p> 2032 * 2033 * <p>An empty ("") String will be returned if no digits found in {@code str}.</p> 2034 * 2035 * <pre> 2036 * StringUtils.getDigits(null) = null 2037 * StringUtils.getDigits("") = "" 2038 * StringUtils.getDigits("abc") = "" 2039 * StringUtils.getDigits("1000$") = "1000" 2040 * StringUtils.getDigits("1123~45") = "112345" 2041 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2042 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2043 * </pre> 2044 * 2045 * @param str the String to extract digits from, may be null 2046 * @return String with only digits, 2047 * or an empty ("") String if no digits found, 2048 * or {@code null} String if {@code str} is null 2049 * @since 3.6 2050 */ 2051 public static String getDigits(final String str) { 2052 if (isEmpty(str)) { 2053 return str; 2054 } 2055 final int sz = str.length(); 2056 final StringBuilder strDigits = new StringBuilder(sz); 2057 for (int i = 0; i < sz; i++) { 2058 final char tempChar = str.charAt(i); 2059 if (Character.isDigit(tempChar)) { 2060 strDigits.append(tempChar); 2061 } 2062 } 2063 return strDigits.toString(); 2064 } 2065 2066 /** 2067 * <p>Find the Fuzzy Distance which indicates the similarity score between two Strings.</p> 2068 * 2069 * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text, 2070 * TextMate, Atom and others. One point is given for every matched character. Subsequent 2071 * matches yield two bonus points. A higher score indicates a higher similarity.</p> 2072 * 2073 * <pre> 2074 * StringUtils.getFuzzyDistance(null, null, null) = IllegalArgumentException 2075 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2076 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2077 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2078 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2079 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2080 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2081 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2082 * </pre> 2083 * 2084 * @param term a full term that should be matched against, must not be null 2085 * @param query the query that will be matched against a term, must not be null 2086 * @param locale This string matching logic is case insensitive. A locale is necessary to normalize 2087 * both Strings to lower case. 2088 * @return result score 2089 * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null} 2090 * @since 3.4 2091 * @deprecated as of 3.6, use commons-text 2092 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2093 * FuzzyScore</a> instead 2094 */ 2095 @Deprecated 2096 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2097 if (term == null || query == null) { 2098 throw new IllegalArgumentException("Strings must not be null"); 2099 } else if (locale == null) { 2100 throw new IllegalArgumentException("Locale must not be null"); 2101 } 2102 2103 // fuzzy logic is case insensitive. We normalize the Strings to lower 2104 // case right from the start. Turning characters to lower case 2105 // via Character.toLowerCase(char) is unfortunately insufficient 2106 // as it does not accept a locale. 2107 final String termLowerCase = term.toString().toLowerCase(locale); 2108 final String queryLowerCase = query.toString().toLowerCase(locale); 2109 2110 // the resulting score 2111 int score = 0; 2112 2113 // the position in the term which will be scanned next for potential 2114 // query character matches 2115 int termIndex = 0; 2116 2117 // index of the previously matched character in the term 2118 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2119 2120 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2121 final char queryChar = queryLowerCase.charAt(queryIndex); 2122 2123 boolean termCharacterMatchFound = false; 2124 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2125 final char termChar = termLowerCase.charAt(termIndex); 2126 2127 if (queryChar == termChar) { 2128 // simple character matches result in one point 2129 score++; 2130 2131 // subsequent character matches further improve 2132 // the score. 2133 if (previousMatchingCharacterIndex + 1 == termIndex) { 2134 score += 2; 2135 } 2136 2137 previousMatchingCharacterIndex = termIndex; 2138 2139 // we can leave the nested loop. Every character in the 2140 // query can match at most one character in the term. 2141 termCharacterMatchFound = true; 2142 } 2143 } 2144 } 2145 2146 return score; 2147 } 2148 2149 /** 2150 * <p>Returns either the passed in CharSequence, or if the CharSequence is 2151 * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}.</p> 2152 * 2153 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 2154 * 2155 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2156 * 2157 * <pre> 2158 * {@code 2159 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2160 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2161 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2162 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2163 * StringUtils.getIfBlank("", () -> null) = null 2164 * StringUtils.getIfBlank("", null) = null 2165 * }</pre> 2166 * @param <T> the specific kind of CharSequence 2167 * @param str the CharSequence to check, may be null 2168 * @param defaultSupplier the supplier of default CharSequence to return 2169 * if the input is whitespace, empty ("") or {@code null}, may be null 2170 * @return the passed in CharSequence, or the default 2171 * @see StringUtils#defaultString(String, String) 2172 * @since 3.10 2173 */ 2174 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2175 return isBlank(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str; 2176 } 2177 2178 /** 2179 * <p>Returns either the passed in CharSequence, or if the CharSequence is 2180 * empty or {@code null}, the value supplied by {@code defaultStrSupplier}.</p> 2181 * 2182 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2183 * 2184 * <pre> 2185 * {@code 2186 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2187 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2188 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2189 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2190 * StringUtils.getIfEmpty("", () -> null) = null 2191 * StringUtils.getIfEmpty("", null) = null 2192 * } 2193 * </pre> 2194 * @param <T> the specific kind of CharSequence 2195 * @param str the CharSequence to check, may be null 2196 * @param defaultSupplier the supplier of default CharSequence to return 2197 * if the input is empty ("") or {@code null}, may be null 2198 * @return the passed in CharSequence, or the default 2199 * @see StringUtils#defaultString(String, String) 2200 * @since 3.10 2201 */ 2202 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2203 return isEmpty(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str; 2204 } 2205 2206 /** 2207 * <p>Find the Jaro Winkler Distance which indicates the similarity score between two Strings.</p> 2208 * 2209 * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. 2210 * Winkler increased this measure for matching initial characters.</p> 2211 * 2212 * <p>This implementation is based on the Jaro Winkler similarity algorithm 2213 * 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> 2214 * 2215 * <pre> 2216 * StringUtils.getJaroWinklerDistance(null, null) = IllegalArgumentException 2217 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2218 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2219 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2220 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2221 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2222 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2223 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2224 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2225 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2226 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2227 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2228 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2229 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2230 * </pre> 2231 * 2232 * @param first the first String, must not be null 2233 * @param second the second String, must not be null 2234 * @return result distance 2235 * @throws IllegalArgumentException if either String input {@code null} 2236 * @since 3.3 2237 * @deprecated as of 3.6, use commons-text 2238 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2239 * JaroWinklerDistance</a> instead 2240 */ 2241 @Deprecated 2242 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2243 final double DEFAULT_SCALING_FACTOR = 0.1; 2244 2245 if (first == null || second == null) { 2246 throw new IllegalArgumentException("Strings must not be null"); 2247 } 2248 2249 final int[] mtp = matches(first, second); 2250 final double m = mtp[0]; 2251 if (m == 0) { 2252 return 0D; 2253 } 2254 final double j = ((m / first.length() + m / second.length() + (m - mtp[1]) / m)) / 3; 2255 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2256 return Math.round(jw * 100.0D) / 100.0D; 2257 } 2258 2259 // Misc 2260 //----------------------------------------------------------------------- 2261 /** 2262 * <p>Find the Levenshtein distance between two Strings.</p> 2263 * 2264 * <p>This is the number of changes needed to change one String into 2265 * another, where each change is a single character modification (deletion, 2266 * insertion or substitution).</p> 2267 * 2268 * <p>The implementation uses a single-dimensional array of length s.length() + 1. See 2269 * <a href="http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2270 * http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p> 2271 * 2272 * <pre> 2273 * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException 2274 * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException 2275 * StringUtils.getLevenshteinDistance("", "") = 0 2276 * StringUtils.getLevenshteinDistance("", "a") = 1 2277 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2278 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2279 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2280 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2281 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2282 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2283 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2284 * </pre> 2285 * 2286 * @param s the first String, must not be null 2287 * @param t the second String, must not be null 2288 * @return result distance 2289 * @throws IllegalArgumentException if either String input {@code null} 2290 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to 2291 * getLevenshteinDistance(CharSequence, CharSequence) 2292 * @deprecated as of 3.6, use commons-text 2293 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2294 * LevenshteinDistance</a> instead 2295 */ 2296 @Deprecated 2297 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2298 if (s == null || t == null) { 2299 throw new IllegalArgumentException("Strings must not be null"); 2300 } 2301 2302 int n = s.length(); 2303 int m = t.length(); 2304 2305 if (n == 0) { 2306 return m; 2307 } else if (m == 0) { 2308 return n; 2309 } 2310 2311 if (n > m) { 2312 // swap the input strings to consume less memory 2313 final CharSequence tmp = s; 2314 s = t; 2315 t = tmp; 2316 n = m; 2317 m = t.length(); 2318 } 2319 2320 final int p[] = new int[n + 1]; 2321 // indexes into strings s and t 2322 int i; // iterates through s 2323 int j; // iterates through t 2324 int upper_left; 2325 int upper; 2326 2327 char t_j; // jth character of t 2328 int cost; 2329 2330 for (i = 0; i <= n; i++) { 2331 p[i] = i; 2332 } 2333 2334 for (j = 1; j <= m; j++) { 2335 upper_left = p[0]; 2336 t_j = t.charAt(j - 1); 2337 p[0] = j; 2338 2339 for (i = 1; i <= n; i++) { 2340 upper = p[i]; 2341 cost = s.charAt(i - 1) == t_j ? 0 : 1; 2342 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2343 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upper_left + cost); 2344 upper_left = upper; 2345 } 2346 } 2347 2348 return p[n]; 2349 } 2350 2351 /** 2352 * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given 2353 * threshold.</p> 2354 * 2355 * <p>This is the number of changes needed to change one String into 2356 * another, where each change is a single character modification (deletion, 2357 * insertion or substitution).</p> 2358 * 2359 * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield 2360 * and Chas Emerick's implementation of the Levenshtein distance algorithm from 2361 * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> 2362 * 2363 * <pre> 2364 * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException 2365 * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException 2366 * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException 2367 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2368 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2369 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2370 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2371 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2372 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2373 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2374 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2375 * </pre> 2376 * 2377 * @param s the first String, must not be null 2378 * @param t the second String, must not be null 2379 * @param threshold the target threshold, must not be negative 2380 * @return result distance, or {@code -1} if the distance would be greater than the threshold 2381 * @throws IllegalArgumentException if either String input {@code null} or negative threshold 2382 * @deprecated as of 3.6, use commons-text 2383 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2384 * LevenshteinDistance</a> instead 2385 */ 2386 @Deprecated 2387 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2388 if (s == null || t == null) { 2389 throw new IllegalArgumentException("Strings must not be null"); 2390 } 2391 if (threshold < 0) { 2392 throw new IllegalArgumentException("Threshold must not be negative"); 2393 } 2394 2395 /* 2396 This implementation only computes the distance if it's less than or equal to the 2397 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2398 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2399 computing a diagonal stripe of width 2k + 1 of the cost table. 2400 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2401 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2402 d is the distance. 2403 2404 One subtlety comes from needing to ignore entries on the border of our stripe 2405 eg. 2406 p[] = |#|#|#|* 2407 d[] = *|#|#|#| 2408 We must ignore the entry to the left of the leftmost member 2409 We must ignore the entry above the rightmost member 2410 2411 Another subtlety comes from our stripe running off the matrix if the strings aren't 2412 of the same size. Since string s is always swapped to be the shorter of the two, 2413 the stripe will always run off to the upper right instead of the lower left of the matrix. 2414 2415 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2416 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2417 2418 1 2 3 4 5 2419 1 |#|#| | | | 2420 2 |#|#|#| | | 2421 3 | |#|#|#| | 2422 4 | | |#|#|#| 2423 5 | | | |#|#| 2424 6 | | | | |#| 2425 7 | | | | | | 2426 2427 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2428 into one of length 7 in edit distance of 1. 2429 2430 Additionally, this implementation decreases memory usage by using two 2431 single-dimensional arrays and swapping them back and forth instead of allocating 2432 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2433 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2434 large values so that entries we don't compute are ignored. 2435 2436 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2437 */ 2438 2439 int n = s.length(); // length of s 2440 int m = t.length(); // length of t 2441 2442 // if one string is empty, the edit distance is necessarily the length of the other 2443 if (n == 0) { 2444 return m <= threshold ? m : -1; 2445 } else if (m == 0) { 2446 return n <= threshold ? n : -1; 2447 } else if (Math.abs(n - m) > threshold) { 2448 // no need to calculate the distance if the length difference is greater than the threshold 2449 return -1; 2450 } 2451 2452 if (n > m) { 2453 // swap the two strings to consume less memory 2454 final CharSequence tmp = s; 2455 s = t; 2456 t = tmp; 2457 n = m; 2458 m = t.length(); 2459 } 2460 2461 int p[] = new int[n + 1]; // 'previous' cost array, horizontally 2462 int d[] = new int[n + 1]; // cost array, horizontally 2463 int _d[]; // placeholder to assist in swapping p and d 2464 2465 // fill in starting table values 2466 final int boundary = Math.min(n, threshold) + 1; 2467 for (int i = 0; i < boundary; i++) { 2468 p[i] = i; 2469 } 2470 // these fills ensure that the value above the rightmost entry of our 2471 // stripe will be ignored in following loop iterations 2472 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2473 Arrays.fill(d, Integer.MAX_VALUE); 2474 2475 // iterates through t 2476 for (int j = 1; j <= m; j++) { 2477 final char t_j = t.charAt(j - 1); // jth character of t 2478 d[0] = j; 2479 2480 // compute stripe indices, constrain to array size 2481 final int min = Math.max(1, j - threshold); 2482 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2483 2484 // the stripe may lead off of the table if s and t are of different sizes 2485 if (min > max) { 2486 return -1; 2487 } 2488 2489 // ignore entry left of leftmost 2490 if (min > 1) { 2491 d[min - 1] = Integer.MAX_VALUE; 2492 } 2493 2494 // iterates through [min, max] in s 2495 for (int i = min; i <= max; i++) { 2496 if (s.charAt(i - 1) == t_j) { 2497 // diagonally left and up 2498 d[i] = p[i - 1]; 2499 } else { 2500 // 1 + minimum of cell to the left, to the top, diagonally left and up 2501 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2502 } 2503 } 2504 2505 // copy current distance counts to 'previous row' distance counts 2506 _d = p; 2507 p = d; 2508 d = _d; 2509 } 2510 2511 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2512 // distance 2513 if (p[n] <= threshold) { 2514 return p[n]; 2515 } 2516 return -1; 2517 } 2518 2519 /** 2520 * <p>Finds the first index within a CharSequence, handling {@code null}. 2521 * This method uses {@link String#indexOf(String, int)} if possible.</p> 2522 * 2523 * <p>A {@code null} CharSequence will return {@code -1}.</p> 2524 * 2525 * <pre> 2526 * StringUtils.indexOf(null, *) = -1 2527 * StringUtils.indexOf(*, null) = -1 2528 * StringUtils.indexOf("", "") = 0 2529 * StringUtils.indexOf("", *) = -1 (except when * = "") 2530 * StringUtils.indexOf("aabaabaa", "a") = 0 2531 * StringUtils.indexOf("aabaabaa", "b") = 2 2532 * StringUtils.indexOf("aabaabaa", "ab") = 1 2533 * StringUtils.indexOf("aabaabaa", "") = 0 2534 * </pre> 2535 * 2536 * @param seq the CharSequence to check, may be null 2537 * @param searchSeq the CharSequence to find, may be null 2538 * @return the first index of the search CharSequence, 2539 * -1 if no match or {@code null} string input 2540 * @since 2.0 2541 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2542 */ 2543 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2544 if (seq == null || searchSeq == null) { 2545 return INDEX_NOT_FOUND; 2546 } 2547 return CharSequenceUtils.indexOf(seq, searchSeq, 0); 2548 } 2549 2550 /** 2551 * <p>Finds the first index within a CharSequence, handling {@code null}. 2552 * This method uses {@link String#indexOf(String, int)} if possible.</p> 2553 * 2554 * <p>A {@code null} CharSequence will return {@code -1}. 2555 * A negative start position is treated as zero. 2556 * An empty ("") search CharSequence always matches. 2557 * A start position greater than the string length only matches 2558 * an empty search CharSequence.</p> 2559 * 2560 * <pre> 2561 * StringUtils.indexOf(null, *, *) = -1 2562 * StringUtils.indexOf(*, null, *) = -1 2563 * StringUtils.indexOf("", "", 0) = 0 2564 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2565 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2566 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2567 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2568 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2569 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2570 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2571 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2572 * StringUtils.indexOf("abc", "", 9) = 3 2573 * </pre> 2574 * 2575 * @param seq the CharSequence to check, may be null 2576 * @param searchSeq the CharSequence to find, may be null 2577 * @param startPos the start position, negative treated as zero 2578 * @return the first index of the search CharSequence (always ≥ startPos), 2579 * -1 if no match or {@code null} string input 2580 * @since 2.0 2581 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2582 */ 2583 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2584 if (seq == null || searchSeq == null) { 2585 return INDEX_NOT_FOUND; 2586 } 2587 return CharSequenceUtils.indexOf(seq, searchSeq, startPos); 2588 } 2589 2590 // IndexOf 2591 //----------------------------------------------------------------------- 2592 /** 2593 * Returns the index within {@code seq} of the first occurrence of 2594 * the specified character. If a character with value 2595 * {@code searchChar} occurs in the character sequence represented by 2596 * {@code seq} {@code CharSequence} object, then the index (in Unicode 2597 * code units) of the first such occurrence is returned. For 2598 * values of {@code searchChar} in the range from 0 to 0xFFFF 2599 * (inclusive), this is the smallest value <i>k</i> such that: 2600 * <blockquote><pre> 2601 * this.charAt(<i>k</i>) == searchChar 2602 * </pre></blockquote> 2603 * is true. For other values of {@code searchChar}, it is the 2604 * smallest value <i>k</i> such that: 2605 * <blockquote><pre> 2606 * this.codePointAt(<i>k</i>) == searchChar 2607 * </pre></blockquote> 2608 * is true. In either case, if no such character occurs in {@code seq}, 2609 * then {@code INDEX_NOT_FOUND (-1)} is returned. 2610 * 2611 * <p>Furthermore, a {@code null} or empty ("") CharSequence will 2612 * return {@code INDEX_NOT_FOUND (-1)}.</p> 2613 * 2614 * <pre> 2615 * StringUtils.indexOf(null, *) = -1 2616 * StringUtils.indexOf("", *) = -1 2617 * StringUtils.indexOf("aabaabaa", 'a') = 0 2618 * StringUtils.indexOf("aabaabaa", 'b') = 2 2619 * </pre> 2620 * 2621 * @param seq the CharSequence to check, may be null 2622 * @param searchChar the character to find 2623 * @return the first index of the search character, 2624 * -1 if no match or {@code null} string input 2625 * @since 2.0 2626 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2627 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String} 2628 */ 2629 public static int indexOf(final CharSequence seq, final int searchChar) { 2630 if (isEmpty(seq)) { 2631 return INDEX_NOT_FOUND; 2632 } 2633 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2634 } 2635 2636 /** 2637 * 2638 * Returns the index within {@code seq} of the first occurrence of the 2639 * specified character, starting the search at the specified index. 2640 * <p> 2641 * If a character with value {@code searchChar} occurs in the 2642 * character sequence represented by the {@code seq} {@code CharSequence} 2643 * object at an index no smaller than {@code startPos}, then 2644 * the index of the first such occurrence is returned. For values 2645 * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), 2646 * this is the smallest value <i>k</i> such that: 2647 * <blockquote><pre> 2648 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2649 * </pre></blockquote> 2650 * is true. For other values of {@code searchChar}, it is the 2651 * smallest value <i>k</i> such that: 2652 * <blockquote><pre> 2653 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2654 * </pre></blockquote> 2655 * is true. In either case, if no such character occurs in {@code seq} 2656 * at or after position {@code startPos}, then 2657 * {@code -1} is returned. 2658 * 2659 * <p> 2660 * There is no restriction on the value of {@code startPos}. If it 2661 * is negative, it has the same effect as if it were zero: this entire 2662 * string may be searched. If it is greater than the length of this 2663 * string, it has the same effect as if it were equal to the length of 2664 * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a 2665 * {@code null} or empty ("") CharSequence will 2666 * return {@code (INDEX_NOT_FOUND) -1}. 2667 * 2668 * <p>All indices are specified in {@code char} values 2669 * (Unicode code units). 2670 * 2671 * <pre> 2672 * StringUtils.indexOf(null, *, *) = -1 2673 * StringUtils.indexOf("", *, *) = -1 2674 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2675 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2676 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2677 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2678 * </pre> 2679 * 2680 * @param seq the CharSequence to check, may be null 2681 * @param searchChar the character to find 2682 * @param startPos the start position, negative treated as zero 2683 * @return the first index of the search character (always ≥ startPos), 2684 * -1 if no match or {@code null} string input 2685 * @since 2.0 2686 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2687 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String} 2688 */ 2689 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2690 if (isEmpty(seq)) { 2691 return INDEX_NOT_FOUND; 2692 } 2693 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2694 } 2695 2696 // IndexOfAny chars 2697 //----------------------------------------------------------------------- 2698 /** 2699 * <p>Search a CharSequence to find the first index of any 2700 * character in the given set of characters.</p> 2701 * 2702 * <p>A {@code null} String will return {@code -1}. 2703 * A {@code null} or zero length search array will return {@code -1}.</p> 2704 * 2705 * <pre> 2706 * StringUtils.indexOfAny(null, *) = -1 2707 * StringUtils.indexOfAny("", *) = -1 2708 * StringUtils.indexOfAny(*, null) = -1 2709 * StringUtils.indexOfAny(*, []) = -1 2710 * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0 2711 * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3 2712 * StringUtils.indexOfAny("aba", ['z']) = -1 2713 * </pre> 2714 * 2715 * @param cs the CharSequence to check, may be null 2716 * @param searchChars the chars to search for, may be null 2717 * @return the index of any of the chars, -1 if no match or null input 2718 * @since 2.0 2719 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2720 */ 2721 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2722 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2723 return INDEX_NOT_FOUND; 2724 } 2725 final int csLen = cs.length(); 2726 final int csLast = csLen - 1; 2727 final int searchLen = searchChars.length; 2728 final int searchLast = searchLen - 1; 2729 for (int i = 0; i < csLen; i++) { 2730 final char ch = cs.charAt(i); 2731 for (int j = 0; j < searchLen; j++) { 2732 if (searchChars[j] == ch) { 2733 if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) { 2734 // ch is a supplementary character 2735 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2736 return i; 2737 } 2738 } else { 2739 return i; 2740 } 2741 } 2742 } 2743 } 2744 return INDEX_NOT_FOUND; 2745 } 2746 2747 // IndexOfAny strings 2748 //----------------------------------------------------------------------- 2749 /** 2750 * <p>Find the first index of any of a set of potential substrings.</p> 2751 * 2752 * <p>A {@code null} CharSequence will return {@code -1}. 2753 * A {@code null} or zero length search array will return {@code -1}. 2754 * A {@code null} search array entry will be ignored, but a search 2755 * array containing "" will return {@code 0} if {@code str} is not 2756 * null. This method uses {@link String#indexOf(String)} if possible.</p> 2757 * 2758 * <pre> 2759 * StringUtils.indexOfAny(null, *) = -1 2760 * StringUtils.indexOfAny(*, null) = -1 2761 * StringUtils.indexOfAny(*, []) = -1 2762 * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"]) = 2 2763 * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"]) = 2 2764 * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"]) = -1 2765 * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1 2766 * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0 2767 * StringUtils.indexOfAny("", [""]) = 0 2768 * StringUtils.indexOfAny("", ["a"]) = -1 2769 * </pre> 2770 * 2771 * @param str the CharSequence to check, may be null 2772 * @param searchStrs the CharSequences to search for, may be null 2773 * @return the first index of any of the searchStrs in str, -1 if no match 2774 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2775 */ 2776 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2777 if (str == null || searchStrs == null) { 2778 return INDEX_NOT_FOUND; 2779 } 2780 2781 // String's can't have a MAX_VALUEth index. 2782 int ret = Integer.MAX_VALUE; 2783 2784 int tmp = 0; 2785 for (final CharSequence search : searchStrs) { 2786 if (search == null) { 2787 continue; 2788 } 2789 tmp = CharSequenceUtils.indexOf(str, search, 0); 2790 if (tmp == INDEX_NOT_FOUND) { 2791 continue; 2792 } 2793 2794 if (tmp < ret) { 2795 ret = tmp; 2796 } 2797 } 2798 2799 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2800 } 2801 2802 /** 2803 * <p>Search a CharSequence to find the first index of any 2804 * character in the given set of characters.</p> 2805 * 2806 * <p>A {@code null} String will return {@code -1}. 2807 * A {@code null} search string will return {@code -1}.</p> 2808 * 2809 * <pre> 2810 * StringUtils.indexOfAny(null, *) = -1 2811 * StringUtils.indexOfAny("", *) = -1 2812 * StringUtils.indexOfAny(*, null) = -1 2813 * StringUtils.indexOfAny(*, "") = -1 2814 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2815 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2816 * StringUtils.indexOfAny("aba", "z") = -1 2817 * </pre> 2818 * 2819 * @param cs the CharSequence to check, may be null 2820 * @param searchChars the chars to search for, may be null 2821 * @return the index of any of the chars, -1 if no match or null input 2822 * @since 2.0 2823 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2824 */ 2825 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2826 if (isEmpty(cs) || isEmpty(searchChars)) { 2827 return INDEX_NOT_FOUND; 2828 } 2829 return indexOfAny(cs, searchChars.toCharArray()); 2830 } 2831 2832 // IndexOfAnyBut chars 2833 //----------------------------------------------------------------------- 2834 /** 2835 * <p>Searches a CharSequence to find the first index of any 2836 * character not in the given set of characters.</p> 2837 * 2838 * <p>A {@code null} CharSequence will return {@code -1}. 2839 * A {@code null} or zero length search array will return {@code -1}.</p> 2840 * 2841 * <pre> 2842 * StringUtils.indexOfAnyBut(null, *) = -1 2843 * StringUtils.indexOfAnyBut("", *) = -1 2844 * StringUtils.indexOfAnyBut(*, null) = -1 2845 * StringUtils.indexOfAnyBut(*, []) = -1 2846 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2847 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2848 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2849 2850 * </pre> 2851 * 2852 * @param cs the CharSequence to check, may be null 2853 * @param searchChars the chars to search for, may be null 2854 * @return the index of any of the chars, -1 if no match or null input 2855 * @since 2.0 2856 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2857 */ 2858 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2859 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2860 return INDEX_NOT_FOUND; 2861 } 2862 final int csLen = cs.length(); 2863 final int csLast = csLen - 1; 2864 final int searchLen = searchChars.length; 2865 final int searchLast = searchLen - 1; 2866 outer: 2867 for (int i = 0; i < csLen; i++) { 2868 final char ch = cs.charAt(i); 2869 for (int j = 0; j < searchLen; j++) { 2870 if (searchChars[j] == ch) { 2871 if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) { 2872 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2873 continue outer; 2874 } 2875 } else { 2876 continue outer; 2877 } 2878 } 2879 } 2880 return i; 2881 } 2882 return INDEX_NOT_FOUND; 2883 } 2884 2885 /** 2886 * <p>Search a CharSequence to find the first index of any 2887 * character not in the given set of characters.</p> 2888 * 2889 * <p>A {@code null} CharSequence will return {@code -1}. 2890 * A {@code null} or empty search string will return {@code -1}.</p> 2891 * 2892 * <pre> 2893 * StringUtils.indexOfAnyBut(null, *) = -1 2894 * StringUtils.indexOfAnyBut("", *) = -1 2895 * StringUtils.indexOfAnyBut(*, null) = -1 2896 * StringUtils.indexOfAnyBut(*, "") = -1 2897 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2898 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2899 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2900 * </pre> 2901 * 2902 * @param seq the CharSequence to check, may be null 2903 * @param searchChars the chars to search for, may be null 2904 * @return the index of any of the chars, -1 if no match or null input 2905 * @since 2.0 2906 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2907 */ 2908 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2909 if (isEmpty(seq) || isEmpty(searchChars)) { 2910 return INDEX_NOT_FOUND; 2911 } 2912 final int strLen = seq.length(); 2913 for (int i = 0; i < strLen; i++) { 2914 final char ch = seq.charAt(i); 2915 final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0; 2916 if (i + 1 < strLen && Character.isHighSurrogate(ch)) { 2917 final char ch2 = seq.charAt(i + 1); 2918 if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) { 2919 return i; 2920 } 2921 } else { 2922 if (!chFound) { 2923 return i; 2924 } 2925 } 2926 } 2927 return INDEX_NOT_FOUND; 2928 } 2929 2930 /** 2931 * <p>Compares all CharSequences in an array and returns the index at which the 2932 * CharSequences begin to differ.</p> 2933 * 2934 * <p>For example, 2935 * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p> 2936 * 2937 * <pre> 2938 * StringUtils.indexOfDifference(null) = -1 2939 * StringUtils.indexOfDifference(new String[] {}) = -1 2940 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 2941 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 2942 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 2943 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 2944 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 2945 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 2946 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 2947 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 2948 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 2949 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 2950 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 2951 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 2952 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 2953 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 2954 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 2955 * </pre> 2956 * 2957 * @param css array of CharSequences, entries may be null 2958 * @return the index where the strings begin to differ; -1 if they are all equal 2959 * @since 2.4 2960 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 2961 */ 2962 public static int indexOfDifference(final CharSequence... css) { 2963 if (ArrayUtils.getLength(css) <= 1) { 2964 return INDEX_NOT_FOUND; 2965 } 2966 boolean anyStringNull = false; 2967 boolean allStringsNull = true; 2968 final int arrayLen = css.length; 2969 int shortestStrLen = Integer.MAX_VALUE; 2970 int longestStrLen = 0; 2971 2972 // find the min and max string lengths; this avoids checking to make 2973 // sure we are not exceeding the length of the string each time through 2974 // the bottom loop. 2975 for (final CharSequence cs : css) { 2976 if (cs == null) { 2977 anyStringNull = true; 2978 shortestStrLen = 0; 2979 } else { 2980 allStringsNull = false; 2981 shortestStrLen = Math.min(cs.length(), shortestStrLen); 2982 longestStrLen = Math.max(cs.length(), longestStrLen); 2983 } 2984 } 2985 2986 // handle lists containing all nulls or all empty strings 2987 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 2988 return INDEX_NOT_FOUND; 2989 } 2990 2991 // handle lists containing some nulls or some empty strings 2992 if (shortestStrLen == 0) { 2993 return 0; 2994 } 2995 2996 // find the position with the first difference across all strings 2997 int firstDiff = -1; 2998 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 2999 final char comparisonChar = css[0].charAt(stringPos); 3000 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 3001 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 3002 firstDiff = stringPos; 3003 break; 3004 } 3005 } 3006 if (firstDiff != -1) { 3007 break; 3008 } 3009 } 3010 3011 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 3012 // we compared all of the characters up to the length of the 3013 // shortest string and didn't find a match, but the string lengths 3014 // vary, so return the length of the shortest string. 3015 return shortestStrLen; 3016 } 3017 return firstDiff; 3018 } 3019 3020 /** 3021 * <p>Compares two CharSequences, and returns the index at which the 3022 * CharSequences begin to differ.</p> 3023 * 3024 * <p>For example, 3025 * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p> 3026 * 3027 * <pre> 3028 * StringUtils.indexOfDifference(null, null) = -1 3029 * StringUtils.indexOfDifference("", "") = -1 3030 * StringUtils.indexOfDifference("", "abc") = 0 3031 * StringUtils.indexOfDifference("abc", "") = 0 3032 * StringUtils.indexOfDifference("abc", "abc") = -1 3033 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3034 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3035 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3036 * </pre> 3037 * 3038 * @param cs1 the first CharSequence, may be null 3039 * @param cs2 the second CharSequence, may be null 3040 * @return the index where cs1 and cs2 begin to differ; -1 if they are equal 3041 * @since 2.0 3042 * @since 3.0 Changed signature from indexOfDifference(String, String) to 3043 * indexOfDifference(CharSequence, CharSequence) 3044 */ 3045 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3046 if (cs1 == cs2) { 3047 return INDEX_NOT_FOUND; 3048 } 3049 if (cs1 == null || cs2 == null) { 3050 return 0; 3051 } 3052 int i; 3053 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3054 if (cs1.charAt(i) != cs2.charAt(i)) { 3055 break; 3056 } 3057 } 3058 if (i < cs2.length() || i < cs1.length()) { 3059 return i; 3060 } 3061 return INDEX_NOT_FOUND; 3062 } 3063 3064 /** 3065 * <p>Case in-sensitive find of the first index within a CharSequence.</p> 3066 * 3067 * <p>A {@code null} CharSequence will return {@code -1}. 3068 * A negative start position is treated as zero. 3069 * An empty ("") search CharSequence always matches. 3070 * A start position greater than the string length only matches 3071 * an empty search CharSequence.</p> 3072 * 3073 * <pre> 3074 * StringUtils.indexOfIgnoreCase(null, *) = -1 3075 * StringUtils.indexOfIgnoreCase(*, null) = -1 3076 * StringUtils.indexOfIgnoreCase("", "") = 0 3077 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3078 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3079 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3080 * </pre> 3081 * 3082 * @param str the CharSequence to check, may be null 3083 * @param searchStr the CharSequence to find, may be null 3084 * @return the first index of the search CharSequence, 3085 * -1 if no match or {@code null} string input 3086 * @since 2.5 3087 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3088 */ 3089 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3090 return indexOfIgnoreCase(str, searchStr, 0); 3091 } 3092 3093 /** 3094 * <p>Case in-sensitive find of the first index within a CharSequence 3095 * from the specified position.</p> 3096 * 3097 * <p>A {@code null} CharSequence will return {@code -1}. 3098 * A negative start position is treated as zero. 3099 * An empty ("") search CharSequence always matches. 3100 * A start position greater than the string length only matches 3101 * an empty search CharSequence.</p> 3102 * 3103 * <pre> 3104 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3105 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3106 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3107 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3108 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3109 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3110 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3111 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3112 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3113 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3114 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3115 * </pre> 3116 * 3117 * @param str the CharSequence to check, may be null 3118 * @param searchStr the CharSequence to find, may be null 3119 * @param startPos the start position, negative treated as zero 3120 * @return the first index of the search CharSequence (always ≥ startPos), 3121 * -1 if no match or {@code null} string input 3122 * @since 2.5 3123 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3124 */ 3125 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 3126 if (str == null || searchStr == null) { 3127 return INDEX_NOT_FOUND; 3128 } 3129 if (startPos < 0) { 3130 startPos = 0; 3131 } 3132 final int endLimit = str.length() - searchStr.length() + 1; 3133 if (startPos > endLimit) { 3134 return INDEX_NOT_FOUND; 3135 } 3136 if (searchStr.length() == 0) { 3137 return startPos; 3138 } 3139 for (int i = startPos; i < endLimit; i++) { 3140 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 3141 return i; 3142 } 3143 } 3144 return INDEX_NOT_FOUND; 3145 } 3146 3147 /** 3148 * <p>Checks if all of the CharSequences are empty (""), null or whitespace only.</p> 3149 * 3150 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3151 * 3152 * <pre> 3153 * StringUtils.isAllBlank(null) = true 3154 * StringUtils.isAllBlank(null, "foo") = false 3155 * StringUtils.isAllBlank(null, null) = true 3156 * StringUtils.isAllBlank("", "bar") = false 3157 * StringUtils.isAllBlank("bob", "") = false 3158 * StringUtils.isAllBlank(" bob ", null) = false 3159 * StringUtils.isAllBlank(" ", "bar") = false 3160 * StringUtils.isAllBlank("foo", "bar") = false 3161 * StringUtils.isAllBlank(new String[] {}) = true 3162 * </pre> 3163 * 3164 * @param css the CharSequences to check, may be null or empty 3165 * @return {@code true} if all of the CharSequences are empty or null or whitespace only 3166 * @since 3.6 3167 */ 3168 public static boolean isAllBlank(final CharSequence... css) { 3169 if (ArrayUtils.isEmpty(css)) { 3170 return true; 3171 } 3172 for (final CharSequence cs : css) { 3173 if (isNotBlank(cs)) { 3174 return false; 3175 } 3176 } 3177 return true; 3178 } 3179 3180 /** 3181 * <p>Checks if all of the CharSequences are empty ("") or null.</p> 3182 * 3183 * <pre> 3184 * StringUtils.isAllEmpty(null) = true 3185 * StringUtils.isAllEmpty(null, "") = true 3186 * StringUtils.isAllEmpty(new String[] {}) = true 3187 * StringUtils.isAllEmpty(null, "foo") = false 3188 * StringUtils.isAllEmpty("", "bar") = false 3189 * StringUtils.isAllEmpty("bob", "") = false 3190 * StringUtils.isAllEmpty(" bob ", null) = false 3191 * StringUtils.isAllEmpty(" ", "bar") = false 3192 * StringUtils.isAllEmpty("foo", "bar") = false 3193 * </pre> 3194 * 3195 * @param css the CharSequences to check, may be null or empty 3196 * @return {@code true} if all of the CharSequences are empty or null 3197 * @since 3.6 3198 */ 3199 public static boolean isAllEmpty(final CharSequence... css) { 3200 if (ArrayUtils.isEmpty(css)) { 3201 return true; 3202 } 3203 for (final CharSequence cs : css) { 3204 if (isNotEmpty(cs)) { 3205 return false; 3206 } 3207 } 3208 return true; 3209 } 3210 3211 /** 3212 * <p>Checks if the CharSequence contains only lowercase characters.</p> 3213 * 3214 * <p>{@code null} will return {@code false}. 3215 * An empty CharSequence (length()=0) will return {@code false}.</p> 3216 * 3217 * <pre> 3218 * StringUtils.isAllLowerCase(null) = false 3219 * StringUtils.isAllLowerCase("") = false 3220 * StringUtils.isAllLowerCase(" ") = false 3221 * StringUtils.isAllLowerCase("abc") = true 3222 * StringUtils.isAllLowerCase("abC") = false 3223 * StringUtils.isAllLowerCase("ab c") = false 3224 * StringUtils.isAllLowerCase("ab1c") = false 3225 * StringUtils.isAllLowerCase("ab/c") = false 3226 * </pre> 3227 * 3228 * @param cs the CharSequence to check, may be null 3229 * @return {@code true} if only contains lowercase characters, and is non-null 3230 * @since 2.5 3231 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3232 */ 3233 public static boolean isAllLowerCase(final CharSequence cs) { 3234 if (isEmpty(cs)) { 3235 return false; 3236 } 3237 final int sz = cs.length(); 3238 for (int i = 0; i < sz; i++) { 3239 if (!Character.isLowerCase(cs.charAt(i))) { 3240 return false; 3241 } 3242 } 3243 return true; 3244 } 3245 3246 /** 3247 * <p>Checks if the CharSequence contains only uppercase characters.</p> 3248 * 3249 * <p>{@code null} will return {@code false}. 3250 * An empty String (length()=0) will return {@code false}.</p> 3251 * 3252 * <pre> 3253 * StringUtils.isAllUpperCase(null) = false 3254 * StringUtils.isAllUpperCase("") = false 3255 * StringUtils.isAllUpperCase(" ") = false 3256 * StringUtils.isAllUpperCase("ABC") = true 3257 * StringUtils.isAllUpperCase("aBC") = false 3258 * StringUtils.isAllUpperCase("A C") = false 3259 * StringUtils.isAllUpperCase("A1C") = false 3260 * StringUtils.isAllUpperCase("A/C") = false 3261 * </pre> 3262 * 3263 * @param cs the CharSequence to check, may be null 3264 * @return {@code true} if only contains uppercase characters, and is non-null 3265 * @since 2.5 3266 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3267 */ 3268 public static boolean isAllUpperCase(final CharSequence cs) { 3269 if (isEmpty(cs)) { 3270 return false; 3271 } 3272 final int sz = cs.length(); 3273 for (int i = 0; i < sz; i++) { 3274 if (!Character.isUpperCase(cs.charAt(i))) { 3275 return false; 3276 } 3277 } 3278 return true; 3279 } 3280 3281 // Character Tests 3282 //----------------------------------------------------------------------- 3283 /** 3284 * <p>Checks if the CharSequence contains only Unicode letters.</p> 3285 * 3286 * <p>{@code null} will return {@code false}. 3287 * An empty CharSequence (length()=0) will return {@code false}.</p> 3288 * 3289 * <pre> 3290 * StringUtils.isAlpha(null) = false 3291 * StringUtils.isAlpha("") = false 3292 * StringUtils.isAlpha(" ") = false 3293 * StringUtils.isAlpha("abc") = true 3294 * StringUtils.isAlpha("ab2c") = false 3295 * StringUtils.isAlpha("ab-c") = false 3296 * </pre> 3297 * 3298 * @param cs the CharSequence to check, may be null 3299 * @return {@code true} if only contains letters, and is non-null 3300 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3301 * @since 3.0 Changed "" to return false and not true 3302 */ 3303 public static boolean isAlpha(final CharSequence cs) { 3304 if (isEmpty(cs)) { 3305 return false; 3306 } 3307 final int sz = cs.length(); 3308 for (int i = 0; i < sz; i++) { 3309 if (!Character.isLetter(cs.charAt(i))) { 3310 return false; 3311 } 3312 } 3313 return true; 3314 } 3315 3316 /** 3317 * <p>Checks if the CharSequence contains only Unicode letters or digits.</p> 3318 * 3319 * <p>{@code null} will return {@code false}. 3320 * An empty CharSequence (length()=0) will return {@code false}.</p> 3321 * 3322 * <pre> 3323 * StringUtils.isAlphanumeric(null) = false 3324 * StringUtils.isAlphanumeric("") = false 3325 * StringUtils.isAlphanumeric(" ") = false 3326 * StringUtils.isAlphanumeric("abc") = true 3327 * StringUtils.isAlphanumeric("ab c") = false 3328 * StringUtils.isAlphanumeric("ab2c") = true 3329 * StringUtils.isAlphanumeric("ab-c") = false 3330 * </pre> 3331 * 3332 * @param cs the CharSequence to check, may be null 3333 * @return {@code true} if only contains letters or digits, 3334 * and is non-null 3335 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3336 * @since 3.0 Changed "" to return false and not true 3337 */ 3338 public static boolean isAlphanumeric(final CharSequence cs) { 3339 if (isEmpty(cs)) { 3340 return false; 3341 } 3342 final int sz = cs.length(); 3343 for (int i = 0; i < sz; i++) { 3344 if (!Character.isLetterOrDigit(cs.charAt(i))) { 3345 return false; 3346 } 3347 } 3348 return true; 3349 } 3350 3351 /** 3352 * <p>Checks if the CharSequence contains only Unicode letters, digits 3353 * or space ({@code ' '}).</p> 3354 * 3355 * <p>{@code null} will return {@code false}. 3356 * An empty CharSequence (length()=0) will return {@code true}.</p> 3357 * 3358 * <pre> 3359 * StringUtils.isAlphanumericSpace(null) = false 3360 * StringUtils.isAlphanumericSpace("") = true 3361 * StringUtils.isAlphanumericSpace(" ") = true 3362 * StringUtils.isAlphanumericSpace("abc") = true 3363 * StringUtils.isAlphanumericSpace("ab c") = true 3364 * StringUtils.isAlphanumericSpace("ab2c") = true 3365 * StringUtils.isAlphanumericSpace("ab-c") = false 3366 * </pre> 3367 * 3368 * @param cs the CharSequence to check, may be null 3369 * @return {@code true} if only contains letters, digits or space, 3370 * and is non-null 3371 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3372 */ 3373 public static boolean isAlphanumericSpace(final CharSequence cs) { 3374 if (cs == null) { 3375 return false; 3376 } 3377 final int sz = cs.length(); 3378 for (int i = 0; i < sz; i++) { 3379 if (!Character.isLetterOrDigit(cs.charAt(i)) && cs.charAt(i) != ' ') { 3380 return false; 3381 } 3382 } 3383 return true; 3384 } 3385 3386 /** 3387 * <p>Checks if the CharSequence contains only Unicode letters and 3388 * space (' ').</p> 3389 * 3390 * <p>{@code null} will return {@code false} 3391 * An empty CharSequence (length()=0) will return {@code true}.</p> 3392 * 3393 * <pre> 3394 * StringUtils.isAlphaSpace(null) = false 3395 * StringUtils.isAlphaSpace("") = true 3396 * StringUtils.isAlphaSpace(" ") = true 3397 * StringUtils.isAlphaSpace("abc") = true 3398 * StringUtils.isAlphaSpace("ab c") = true 3399 * StringUtils.isAlphaSpace("ab2c") = false 3400 * StringUtils.isAlphaSpace("ab-c") = false 3401 * </pre> 3402 * 3403 * @param cs the CharSequence to check, may be null 3404 * @return {@code true} if only contains letters and space, 3405 * and is non-null 3406 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3407 */ 3408 public static boolean isAlphaSpace(final CharSequence cs) { 3409 if (cs == null) { 3410 return false; 3411 } 3412 final int sz = cs.length(); 3413 for (int i = 0; i < sz; i++) { 3414 if (!Character.isLetter(cs.charAt(i)) && cs.charAt(i) != ' ') { 3415 return false; 3416 } 3417 } 3418 return true; 3419 } 3420 3421 /** 3422 * <p>Checks if any of the CharSequences are empty ("") or null or whitespace only.</p> 3423 * 3424 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3425 * 3426 * <pre> 3427 * StringUtils.isAnyBlank((String) null) = true 3428 * StringUtils.isAnyBlank((String[]) null) = false 3429 * StringUtils.isAnyBlank(null, "foo") = true 3430 * StringUtils.isAnyBlank(null, null) = true 3431 * StringUtils.isAnyBlank("", "bar") = true 3432 * StringUtils.isAnyBlank("bob", "") = true 3433 * StringUtils.isAnyBlank(" bob ", null) = true 3434 * StringUtils.isAnyBlank(" ", "bar") = true 3435 * StringUtils.isAnyBlank(new String[] {}) = false 3436 * StringUtils.isAnyBlank(new String[]{""}) = true 3437 * StringUtils.isAnyBlank("foo", "bar") = false 3438 * </pre> 3439 * 3440 * @param css the CharSequences to check, may be null or empty 3441 * @return {@code true} if any of the CharSequences are empty or null or whitespace only 3442 * @since 3.2 3443 */ 3444 public static boolean isAnyBlank(final CharSequence... css) { 3445 if (ArrayUtils.isEmpty(css)) { 3446 return false; 3447 } 3448 for (final CharSequence cs : css) { 3449 if (isBlank(cs)) { 3450 return true; 3451 } 3452 } 3453 return false; 3454 } 3455 3456 /** 3457 * <p>Checks if any of the CharSequences are empty ("") or null.</p> 3458 * 3459 * <pre> 3460 * StringUtils.isAnyEmpty((String) null) = true 3461 * StringUtils.isAnyEmpty((String[]) null) = false 3462 * StringUtils.isAnyEmpty(null, "foo") = true 3463 * StringUtils.isAnyEmpty("", "bar") = true 3464 * StringUtils.isAnyEmpty("bob", "") = true 3465 * StringUtils.isAnyEmpty(" bob ", null) = true 3466 * StringUtils.isAnyEmpty(" ", "bar") = false 3467 * StringUtils.isAnyEmpty("foo", "bar") = false 3468 * StringUtils.isAnyEmpty(new String[]{}) = false 3469 * StringUtils.isAnyEmpty(new String[]{""}) = true 3470 * </pre> 3471 * 3472 * @param css the CharSequences to check, may be null or empty 3473 * @return {@code true} if any of the CharSequences are empty or null 3474 * @since 3.2 3475 */ 3476 public static boolean isAnyEmpty(final CharSequence... css) { 3477 if (ArrayUtils.isEmpty(css)) { 3478 return false; 3479 } 3480 for (final CharSequence cs : css) { 3481 if (isEmpty(cs)) { 3482 return true; 3483 } 3484 } 3485 return false; 3486 } 3487 3488 /** 3489 * <p>Checks if the CharSequence contains only ASCII printable characters.</p> 3490 * 3491 * <p>{@code null} will return {@code false}. 3492 * An empty CharSequence (length()=0) will return {@code true}.</p> 3493 * 3494 * <pre> 3495 * StringUtils.isAsciiPrintable(null) = false 3496 * StringUtils.isAsciiPrintable("") = true 3497 * StringUtils.isAsciiPrintable(" ") = true 3498 * StringUtils.isAsciiPrintable("Ceki") = true 3499 * StringUtils.isAsciiPrintable("ab2c") = true 3500 * StringUtils.isAsciiPrintable("!ab-c~") = true 3501 * StringUtils.isAsciiPrintable("\u0020") = true 3502 * StringUtils.isAsciiPrintable("\u0021") = true 3503 * StringUtils.isAsciiPrintable("\u007e") = true 3504 * StringUtils.isAsciiPrintable("\u007f") = false 3505 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3506 * </pre> 3507 * 3508 * @param cs the CharSequence to check, may be null 3509 * @return {@code true} if every character is in the range 3510 * 32 thru 126 3511 * @since 2.1 3512 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3513 */ 3514 public static boolean isAsciiPrintable(final CharSequence cs) { 3515 if (cs == null) { 3516 return false; 3517 } 3518 final int sz = cs.length(); 3519 for (int i = 0; i < sz; i++) { 3520 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3521 return false; 3522 } 3523 } 3524 return true; 3525 } 3526 3527 // Nested extraction 3528 //----------------------------------------------------------------------- 3529 3530 /** 3531 * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p> 3532 * 3533 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3534 * 3535 * <pre> 3536 * StringUtils.isBlank(null) = true 3537 * StringUtils.isBlank("") = true 3538 * StringUtils.isBlank(" ") = true 3539 * StringUtils.isBlank("bob") = false 3540 * StringUtils.isBlank(" bob ") = false 3541 * </pre> 3542 * 3543 * @param cs the CharSequence to check, may be null 3544 * @return {@code true} if the CharSequence is null, empty or whitespace only 3545 * @since 2.0 3546 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3547 */ 3548 public static boolean isBlank(final CharSequence cs) { 3549 final int strLen = length(cs); 3550 if (strLen == 0) { 3551 return true; 3552 } 3553 for (int i = 0; i < strLen; i++) { 3554 if (!Character.isWhitespace(cs.charAt(i))) { 3555 return false; 3556 } 3557 } 3558 return true; 3559 } 3560 3561 // Empty checks 3562 //----------------------------------------------------------------------- 3563 /** 3564 * <p>Checks if a CharSequence is empty ("") or null.</p> 3565 * 3566 * <pre> 3567 * StringUtils.isEmpty(null) = true 3568 * StringUtils.isEmpty("") = true 3569 * StringUtils.isEmpty(" ") = false 3570 * StringUtils.isEmpty("bob") = false 3571 * StringUtils.isEmpty(" bob ") = false 3572 * </pre> 3573 * 3574 * <p>NOTE: This method changed in Lang version 2.0. 3575 * It no longer trims the CharSequence. 3576 * That functionality is available in isBlank().</p> 3577 * 3578 * @param cs the CharSequence to check, may be null 3579 * @return {@code true} if the CharSequence is empty or null 3580 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3581 */ 3582 public static boolean isEmpty(final CharSequence cs) { 3583 return cs == null || cs.length() == 0; 3584 } 3585 3586 /** 3587 * <p>Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters.</p> 3588 * 3589 * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return 3590 * {@code false}.</p> 3591 * 3592 * <pre> 3593 * StringUtils.isMixedCase(null) = false 3594 * StringUtils.isMixedCase("") = false 3595 * StringUtils.isMixedCase("ABC") = false 3596 * StringUtils.isMixedCase("abc") = false 3597 * StringUtils.isMixedCase("aBc") = true 3598 * StringUtils.isMixedCase("A c") = true 3599 * StringUtils.isMixedCase("A1c") = true 3600 * StringUtils.isMixedCase("a/C") = true 3601 * StringUtils.isMixedCase("aC\t") = true 3602 * </pre> 3603 * 3604 * @param cs the CharSequence to check, may be null 3605 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters 3606 * @since 3.5 3607 */ 3608 public static boolean isMixedCase(final CharSequence cs) { 3609 if (isEmpty(cs) || cs.length() == 1) { 3610 return false; 3611 } 3612 boolean containsUppercase = false; 3613 boolean containsLowercase = false; 3614 final int sz = cs.length(); 3615 for (int i = 0; i < sz; i++) { 3616 if (containsUppercase && containsLowercase) { 3617 return true; 3618 } else if (Character.isUpperCase(cs.charAt(i))) { 3619 containsUppercase = true; 3620 } else if (Character.isLowerCase(cs.charAt(i))) { 3621 containsLowercase = true; 3622 } 3623 } 3624 return containsUppercase && containsLowercase; 3625 } 3626 3627 /** 3628 * <p>Checks if none of the CharSequences are empty (""), null or whitespace only.</p> 3629 * 3630 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3631 * 3632 * <pre> 3633 * StringUtils.isNoneBlank((String) null) = false 3634 * StringUtils.isNoneBlank((String[]) null) = true 3635 * StringUtils.isNoneBlank(null, "foo") = false 3636 * StringUtils.isNoneBlank(null, null) = false 3637 * StringUtils.isNoneBlank("", "bar") = false 3638 * StringUtils.isNoneBlank("bob", "") = false 3639 * StringUtils.isNoneBlank(" bob ", null) = false 3640 * StringUtils.isNoneBlank(" ", "bar") = false 3641 * StringUtils.isNoneBlank(new String[] {}) = true 3642 * StringUtils.isNoneBlank(new String[]{""}) = false 3643 * StringUtils.isNoneBlank("foo", "bar") = true 3644 * </pre> 3645 * 3646 * @param css the CharSequences to check, may be null or empty 3647 * @return {@code true} if none of the CharSequences are empty or null or whitespace only 3648 * @since 3.2 3649 */ 3650 public static boolean isNoneBlank(final CharSequence... css) { 3651 return !isAnyBlank(css); 3652 } 3653 3654 /** 3655 * <p>Checks if none of the CharSequences are empty ("") or null.</p> 3656 * 3657 * <pre> 3658 * StringUtils.isNoneEmpty((String) null) = false 3659 * StringUtils.isNoneEmpty((String[]) null) = true 3660 * StringUtils.isNoneEmpty(null, "foo") = false 3661 * StringUtils.isNoneEmpty("", "bar") = false 3662 * StringUtils.isNoneEmpty("bob", "") = false 3663 * StringUtils.isNoneEmpty(" bob ", null) = false 3664 * StringUtils.isNoneEmpty(new String[] {}) = true 3665 * StringUtils.isNoneEmpty(new String[]{""}) = false 3666 * StringUtils.isNoneEmpty(" ", "bar") = true 3667 * StringUtils.isNoneEmpty("foo", "bar") = true 3668 * </pre> 3669 * 3670 * @param css the CharSequences to check, may be null or empty 3671 * @return {@code true} if none of the CharSequences are empty or null 3672 * @since 3.2 3673 */ 3674 public static boolean isNoneEmpty(final CharSequence... css) { 3675 return !isAnyEmpty(css); 3676 } 3677 3678 /** 3679 * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p> 3680 * 3681 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3682 * 3683 * <pre> 3684 * StringUtils.isNotBlank(null) = false 3685 * StringUtils.isNotBlank("") = false 3686 * StringUtils.isNotBlank(" ") = false 3687 * StringUtils.isNotBlank("bob") = true 3688 * StringUtils.isNotBlank(" bob ") = true 3689 * </pre> 3690 * 3691 * @param cs the CharSequence to check, may be null 3692 * @return {@code true} if the CharSequence is 3693 * not empty and not null and not whitespace only 3694 * @since 2.0 3695 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3696 */ 3697 public static boolean isNotBlank(final CharSequence cs) { 3698 return !isBlank(cs); 3699 } 3700 3701 /** 3702 * <p>Checks if a CharSequence is not empty ("") and not null.</p> 3703 * 3704 * <pre> 3705 * StringUtils.isNotEmpty(null) = false 3706 * StringUtils.isNotEmpty("") = false 3707 * StringUtils.isNotEmpty(" ") = true 3708 * StringUtils.isNotEmpty("bob") = true 3709 * StringUtils.isNotEmpty(" bob ") = true 3710 * </pre> 3711 * 3712 * @param cs the CharSequence to check, may be null 3713 * @return {@code true} if the CharSequence is not empty and not null 3714 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3715 */ 3716 public static boolean isNotEmpty(final CharSequence cs) { 3717 return !isEmpty(cs); 3718 } 3719 3720 /** 3721 * <p>Checks if the CharSequence contains only Unicode digits. 3722 * A decimal point is not a Unicode digit and returns false.</p> 3723 * 3724 * <p>{@code null} will return {@code false}. 3725 * An empty CharSequence (length()=0) will return {@code false}.</p> 3726 * 3727 * <p>Note that the method does not allow for a leading sign, either positive or negative. 3728 * Also, if a String passes the numeric test, it may still generate a NumberFormatException 3729 * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range 3730 * for int or long respectively.</p> 3731 * 3732 * <pre> 3733 * StringUtils.isNumeric(null) = false 3734 * StringUtils.isNumeric("") = false 3735 * StringUtils.isNumeric(" ") = false 3736 * StringUtils.isNumeric("123") = true 3737 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3738 * StringUtils.isNumeric("12 3") = false 3739 * StringUtils.isNumeric("ab2c") = false 3740 * StringUtils.isNumeric("12-3") = false 3741 * StringUtils.isNumeric("12.3") = false 3742 * StringUtils.isNumeric("-123") = false 3743 * StringUtils.isNumeric("+123") = false 3744 * </pre> 3745 * 3746 * @param cs the CharSequence to check, may be null 3747 * @return {@code true} if only contains digits, and is non-null 3748 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3749 * @since 3.0 Changed "" to return false and not true 3750 */ 3751 public static boolean isNumeric(final CharSequence cs) { 3752 if (isEmpty(cs)) { 3753 return false; 3754 } 3755 final int sz = cs.length(); 3756 for (int i = 0; i < sz; i++) { 3757 if (!Character.isDigit(cs.charAt(i))) { 3758 return false; 3759 } 3760 } 3761 return true; 3762 } 3763 3764 /** 3765 * <p>Checks if the CharSequence contains only Unicode digits or space 3766 * ({@code ' '}). 3767 * A decimal point is not a Unicode digit and returns false.</p> 3768 * 3769 * <p>{@code null} will return {@code false}. 3770 * An empty CharSequence (length()=0) will return {@code true}.</p> 3771 * 3772 * <pre> 3773 * StringUtils.isNumericSpace(null) = false 3774 * StringUtils.isNumericSpace("") = true 3775 * StringUtils.isNumericSpace(" ") = true 3776 * StringUtils.isNumericSpace("123") = true 3777 * StringUtils.isNumericSpace("12 3") = true 3778 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3779 * StringUtils.isNumeric("\u0967\u0968 \u0969") = true 3780 * StringUtils.isNumericSpace("ab2c") = false 3781 * StringUtils.isNumericSpace("12-3") = false 3782 * StringUtils.isNumericSpace("12.3") = false 3783 * </pre> 3784 * 3785 * @param cs the CharSequence to check, may be null 3786 * @return {@code true} if only contains digits or space, 3787 * and is non-null 3788 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3789 */ 3790 public static boolean isNumericSpace(final CharSequence cs) { 3791 if (cs == null) { 3792 return false; 3793 } 3794 final int sz = cs.length(); 3795 for (int i = 0; i < sz; i++) { 3796 if (!Character.isDigit(cs.charAt(i)) && cs.charAt(i) != ' ') { 3797 return false; 3798 } 3799 } 3800 return true; 3801 } 3802 3803 /** 3804 * <p>Checks if the CharSequence contains only whitespace.</p> 3805 * 3806 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3807 * 3808 * <p>{@code null} will return {@code false}. 3809 * An empty CharSequence (length()=0) will return {@code true}.</p> 3810 * 3811 * <pre> 3812 * StringUtils.isWhitespace(null) = false 3813 * StringUtils.isWhitespace("") = true 3814 * StringUtils.isWhitespace(" ") = true 3815 * StringUtils.isWhitespace("abc") = false 3816 * StringUtils.isWhitespace("ab2c") = false 3817 * StringUtils.isWhitespace("ab-c") = false 3818 * </pre> 3819 * 3820 * @param cs the CharSequence to check, may be null 3821 * @return {@code true} if only contains whitespace, and is non-null 3822 * @since 2.0 3823 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3824 */ 3825 public static boolean isWhitespace(final CharSequence cs) { 3826 if (cs == null) { 3827 return false; 3828 } 3829 final int sz = cs.length(); 3830 for (int i = 0; i < sz; i++) { 3831 if (!Character.isWhitespace(cs.charAt(i))) { 3832 return false; 3833 } 3834 } 3835 return true; 3836 } 3837 3838 /** 3839 * <p> 3840 * Joins the elements of the provided array into a single String containing the provided list of elements. 3841 * </p> 3842 * 3843 * <p> 3844 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3845 * by empty strings. 3846 * </p> 3847 * 3848 * <pre> 3849 * StringUtils.join(null, *) = null 3850 * StringUtils.join([], *) = "" 3851 * StringUtils.join([null], *) = "" 3852 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3853 * StringUtils.join([1, 2, 3], null) = "123" 3854 * </pre> 3855 * 3856 * @param array 3857 * the array of values to join together, may be null 3858 * @param separator 3859 * the separator character to use 3860 * @return the joined String, {@code null} if null array input 3861 * @since 3.2 3862 */ 3863 public static String join(final byte[] array, final char separator) { 3864 if (array == null) { 3865 return null; 3866 } 3867 return join(array, separator, 0, array.length); 3868 } 3869 3870 /** 3871 * <p> 3872 * Joins the elements of the provided array into a single String containing the provided list of elements. 3873 * </p> 3874 * 3875 * <p> 3876 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3877 * by empty strings. 3878 * </p> 3879 * 3880 * <pre> 3881 * StringUtils.join(null, *) = null 3882 * StringUtils.join([], *) = "" 3883 * StringUtils.join([null], *) = "" 3884 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3885 * StringUtils.join([1, 2, 3], null) = "123" 3886 * </pre> 3887 * 3888 * @param array 3889 * the array of values to join together, may be null 3890 * @param separator 3891 * the separator character to use 3892 * @param startIndex 3893 * the first index to start joining from. It is an error to pass in a start index past the end of the 3894 * array 3895 * @param endIndex 3896 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3897 * the array 3898 * @return the joined String, {@code null} if null array input 3899 * @since 3.2 3900 */ 3901 public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) { 3902 if (array == null) { 3903 return null; 3904 } 3905 final int noOfItems = endIndex - startIndex; 3906 if (noOfItems <= 0) { 3907 return EMPTY; 3908 } 3909 final StringBuilder buf = newStringBuilder(noOfItems); 3910 buf.append(array[startIndex]); 3911 for (int i = startIndex + 1; i < endIndex; i++) { 3912 buf.append(separator); 3913 buf.append(array[i]); 3914 } 3915 return buf.toString(); 3916 } 3917 3918 /** 3919 * <p> 3920 * Joins the elements of the provided array into a single String containing the provided list of elements. 3921 * </p> 3922 * 3923 * <p> 3924 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3925 * by empty strings. 3926 * </p> 3927 * 3928 * <pre> 3929 * StringUtils.join(null, *) = null 3930 * StringUtils.join([], *) = "" 3931 * StringUtils.join([null], *) = "" 3932 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3933 * StringUtils.join([1, 2, 3], null) = "123" 3934 * </pre> 3935 * 3936 * @param array 3937 * the array of values to join together, may be null 3938 * @param separator 3939 * the separator character to use 3940 * @return the joined String, {@code null} if null array input 3941 * @since 3.2 3942 */ 3943 public static String join(final char[] array, final char separator) { 3944 if (array == null) { 3945 return null; 3946 } 3947 return join(array, separator, 0, array.length); 3948 } 3949 3950 /** 3951 * <p> 3952 * Joins the elements of the provided array into a single String containing the provided list of elements. 3953 * </p> 3954 * 3955 * <p> 3956 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3957 * by empty strings. 3958 * </p> 3959 * 3960 * <pre> 3961 * StringUtils.join(null, *) = null 3962 * StringUtils.join([], *) = "" 3963 * StringUtils.join([null], *) = "" 3964 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3965 * StringUtils.join([1, 2, 3], null) = "123" 3966 * </pre> 3967 * 3968 * @param array 3969 * the array of values to join together, may be null 3970 * @param separator 3971 * the separator character to use 3972 * @param startIndex 3973 * the first index to start joining from. It is an error to pass in a start index past the end of the 3974 * array 3975 * @param endIndex 3976 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3977 * the array 3978 * @return the joined String, {@code null} if null array input 3979 * @since 3.2 3980 */ 3981 public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) { 3982 if (array == null) { 3983 return null; 3984 } 3985 final int noOfItems = endIndex - startIndex; 3986 if (noOfItems <= 0) { 3987 return EMPTY; 3988 } 3989 final StringBuilder buf = newStringBuilder(noOfItems); 3990 buf.append(array[startIndex]); 3991 for (int i = startIndex + 1; i < endIndex; i++) { 3992 buf.append(separator); 3993 buf.append(array[i]); 3994 } 3995 return buf.toString(); 3996 } 3997 3998 /** 3999 * <p> 4000 * Joins the elements of the provided array into a single String containing the provided list of elements. 4001 * </p> 4002 * 4003 * <p> 4004 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4005 * by empty strings. 4006 * </p> 4007 * 4008 * <pre> 4009 * StringUtils.join(null, *) = null 4010 * StringUtils.join([], *) = "" 4011 * StringUtils.join([null], *) = "" 4012 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4013 * StringUtils.join([1, 2, 3], null) = "123" 4014 * </pre> 4015 * 4016 * @param array 4017 * the array of values to join together, may be null 4018 * @param separator 4019 * the separator character to use 4020 * @return the joined String, {@code null} if null array input 4021 * @since 3.2 4022 */ 4023 public static String join(final double[] array, final char separator) { 4024 if (array == null) { 4025 return null; 4026 } 4027 return join(array, separator, 0, array.length); 4028 } 4029 4030 /** 4031 * <p> 4032 * Joins the elements of the provided array into a single String containing the provided list of elements. 4033 * </p> 4034 * 4035 * <p> 4036 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4037 * by empty strings. 4038 * </p> 4039 * 4040 * <pre> 4041 * StringUtils.join(null, *) = null 4042 * StringUtils.join([], *) = "" 4043 * StringUtils.join([null], *) = "" 4044 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4045 * StringUtils.join([1, 2, 3], null) = "123" 4046 * </pre> 4047 * 4048 * @param array 4049 * the array of values to join together, may be null 4050 * @param separator 4051 * the separator character to use 4052 * @param startIndex 4053 * the first index to start joining from. It is an error to pass in a start index past the end of the 4054 * array 4055 * @param endIndex 4056 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4057 * the array 4058 * @return the joined String, {@code null} if null array input 4059 * @since 3.2 4060 */ 4061 public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) { 4062 if (array == null) { 4063 return null; 4064 } 4065 final int noOfItems = endIndex - startIndex; 4066 if (noOfItems <= 0) { 4067 return EMPTY; 4068 } 4069 final StringBuilder buf = newStringBuilder(noOfItems); 4070 buf.append(array[startIndex]); 4071 for (int i = startIndex + 1; i < endIndex; i++) { 4072 buf.append(separator); 4073 buf.append(array[i]); 4074 } 4075 return buf.toString(); 4076 } 4077 4078 /** 4079 * <p> 4080 * Joins the elements of the provided array into a single String containing the provided list of elements. 4081 * </p> 4082 * 4083 * <p> 4084 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4085 * by empty strings. 4086 * </p> 4087 * 4088 * <pre> 4089 * StringUtils.join(null, *) = null 4090 * StringUtils.join([], *) = "" 4091 * StringUtils.join([null], *) = "" 4092 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4093 * StringUtils.join([1, 2, 3], null) = "123" 4094 * </pre> 4095 * 4096 * @param array 4097 * the array of values to join together, may be null 4098 * @param separator 4099 * the separator character to use 4100 * @return the joined String, {@code null} if null array input 4101 * @since 3.2 4102 */ 4103 public static String join(final float[] array, final char separator) { 4104 if (array == null) { 4105 return null; 4106 } 4107 return join(array, separator, 0, array.length); 4108 } 4109 4110 /** 4111 * <p> 4112 * Joins the elements of the provided array into a single String containing the provided list of elements. 4113 * </p> 4114 * 4115 * <p> 4116 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4117 * by empty strings. 4118 * </p> 4119 * 4120 * <pre> 4121 * StringUtils.join(null, *) = null 4122 * StringUtils.join([], *) = "" 4123 * StringUtils.join([null], *) = "" 4124 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4125 * StringUtils.join([1, 2, 3], null) = "123" 4126 * </pre> 4127 * 4128 * @param array 4129 * the array of values to join together, may be null 4130 * @param separator 4131 * the separator character to use 4132 * @param startIndex 4133 * the first index to start joining from. It is an error to pass in a start index past the end of the 4134 * array 4135 * @param endIndex 4136 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4137 * the array 4138 * @return the joined String, {@code null} if null array input 4139 * @since 3.2 4140 */ 4141 public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) { 4142 if (array == null) { 4143 return null; 4144 } 4145 final int noOfItems = endIndex - startIndex; 4146 if (noOfItems <= 0) { 4147 return EMPTY; 4148 } 4149 final StringBuilder buf = newStringBuilder(noOfItems); 4150 buf.append(array[startIndex]); 4151 for (int i = startIndex + 1; i < endIndex; i++) { 4152 buf.append(separator); 4153 buf.append(array[i]); 4154 } 4155 return buf.toString(); 4156 } 4157 4158 /** 4159 * <p> 4160 * Joins the elements of the provided array into a single String containing the provided list of elements. 4161 * </p> 4162 * 4163 * <p> 4164 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4165 * by empty strings. 4166 * </p> 4167 * 4168 * <pre> 4169 * StringUtils.join(null, *) = null 4170 * StringUtils.join([], *) = "" 4171 * StringUtils.join([null], *) = "" 4172 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4173 * StringUtils.join([1, 2, 3], null) = "123" 4174 * </pre> 4175 * 4176 * @param array 4177 * the array of values to join together, may be null 4178 * @param separator 4179 * the separator character to use 4180 * @return the joined String, {@code null} if null array input 4181 * @since 3.2 4182 */ 4183 public static String join(final int[] array, final char separator) { 4184 if (array == null) { 4185 return null; 4186 } 4187 return join(array, separator, 0, array.length); 4188 } 4189 4190 /** 4191 * <p> 4192 * Joins the elements of the provided array into a single String containing the provided list of elements. 4193 * </p> 4194 * 4195 * <p> 4196 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4197 * by empty strings. 4198 * </p> 4199 * 4200 * <pre> 4201 * StringUtils.join(null, *) = null 4202 * StringUtils.join([], *) = "" 4203 * StringUtils.join([null], *) = "" 4204 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4205 * StringUtils.join([1, 2, 3], null) = "123" 4206 * </pre> 4207 * 4208 * @param array 4209 * the array of values to join together, may be null 4210 * @param separator 4211 * the separator character to use 4212 * @param startIndex 4213 * the first index to start joining from. It is an error to pass in a start index past the end of the 4214 * array 4215 * @param endIndex 4216 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4217 * the array 4218 * @return the joined String, {@code null} if null array input 4219 * @since 3.2 4220 */ 4221 public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) { 4222 if (array == null) { 4223 return null; 4224 } 4225 final int noOfItems = endIndex - startIndex; 4226 if (noOfItems <= 0) { 4227 return EMPTY; 4228 } 4229 final StringBuilder buf = newStringBuilder(noOfItems); 4230 buf.append(array[startIndex]); 4231 for (int i = startIndex + 1; i < endIndex; i++) { 4232 buf.append(separator); 4233 buf.append(array[i]); 4234 } 4235 return buf.toString(); 4236 } 4237 4238 /** 4239 * <p>Joins the elements of the provided {@code Iterable} into 4240 * a single String containing the provided elements.</p> 4241 * 4242 * <p>No delimiter is added before or after the list. Null objects or empty 4243 * strings within the iteration are represented by empty strings.</p> 4244 * 4245 * <p>See the examples here: {@link #join(Object[],char)}. </p> 4246 * 4247 * @param iterable the {@code Iterable} providing the values to join together, may be null 4248 * @param separator the separator character to use 4249 * @return the joined String, {@code null} if null iterator input 4250 * @since 2.3 4251 */ 4252 public static String join(final Iterable<?> iterable, final char separator) { 4253 if (iterable == null) { 4254 return null; 4255 } 4256 return join(iterable.iterator(), separator); 4257 } 4258 4259 /** 4260 * <p>Joins the elements of the provided {@code Iterable} into 4261 * a single String containing the provided elements.</p> 4262 * 4263 * <p>No delimiter is added before or after the list. 4264 * A {@code null} separator is the same as an empty String ("").</p> 4265 * 4266 * <p>See the examples here: {@link #join(Object[],String)}. </p> 4267 * 4268 * @param iterable the {@code Iterable} providing the values to join together, may be null 4269 * @param separator the separator character to use, null treated as "" 4270 * @return the joined String, {@code null} if null iterator input 4271 * @since 2.3 4272 */ 4273 public static String join(final Iterable<?> iterable, final String separator) { 4274 if (iterable == null) { 4275 return null; 4276 } 4277 return join(iterable.iterator(), separator); 4278 } 4279 4280 /** 4281 * <p>Joins the elements of the provided {@code Iterator} into 4282 * a single String containing the provided elements.</p> 4283 * 4284 * <p>No delimiter is added before or after the list. Null objects or empty 4285 * strings within the iteration are represented by empty strings.</p> 4286 * 4287 * <p>See the examples here: {@link #join(Object[],char)}. </p> 4288 * 4289 * @param iterator the {@code Iterator} of values to join together, may be null 4290 * @param separator the separator character to use 4291 * @return the joined String, {@code null} if null iterator input 4292 * @since 2.0 4293 */ 4294 public static String join(final Iterator<?> iterator, final char separator) { 4295 4296 // handle null, zero and one elements before building a buffer 4297 if (iterator == null) { 4298 return null; 4299 } 4300 if (!iterator.hasNext()) { 4301 return EMPTY; 4302 } 4303 final Object first = iterator.next(); 4304 if (!iterator.hasNext()) { 4305 return Objects.toString(first, EMPTY); 4306 } 4307 4308 // two or more elements 4309 final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small 4310 if (first != null) { 4311 buf.append(first); 4312 } 4313 4314 while (iterator.hasNext()) { 4315 buf.append(separator); 4316 final Object obj = iterator.next(); 4317 if (obj != null) { 4318 buf.append(obj); 4319 } 4320 } 4321 4322 return buf.toString(); 4323 } 4324 4325 /** 4326 * <p>Joins the elements of the provided {@code Iterator} into 4327 * a single String containing the provided elements.</p> 4328 * 4329 * <p>No delimiter is added before or after the list. 4330 * A {@code null} separator is the same as an empty String ("").</p> 4331 * 4332 * <p>See the examples here: {@link #join(Object[],String)}. </p> 4333 * 4334 * @param iterator the {@code Iterator} of values to join together, may be null 4335 * @param separator the separator character to use, null treated as "" 4336 * @return the joined String, {@code null} if null iterator input 4337 */ 4338 public static String join(final Iterator<?> iterator, final String separator) { 4339 4340 // handle null, zero and one elements before building a buffer 4341 if (iterator == null) { 4342 return null; 4343 } 4344 if (!iterator.hasNext()) { 4345 return EMPTY; 4346 } 4347 final Object first = iterator.next(); 4348 if (!iterator.hasNext()) { 4349 return Objects.toString(first, ""); 4350 } 4351 4352 // two or more elements 4353 final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small 4354 if (first != null) { 4355 buf.append(first); 4356 } 4357 4358 while (iterator.hasNext()) { 4359 if (separator != null) { 4360 buf.append(separator); 4361 } 4362 final Object obj = iterator.next(); 4363 if (obj != null) { 4364 buf.append(obj); 4365 } 4366 } 4367 return buf.toString(); 4368 } 4369 4370 /** 4371 * <p>Joins the elements of the provided {@code List} into a single String 4372 * containing the provided list of elements.</p> 4373 * 4374 * <p>No delimiter is added before or after the list. 4375 * Null objects or empty strings within the array are represented by 4376 * empty strings.</p> 4377 * 4378 * <pre> 4379 * StringUtils.join(null, *) = null 4380 * StringUtils.join([], *) = "" 4381 * StringUtils.join([null], *) = "" 4382 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4383 * StringUtils.join(["a", "b", "c"], null) = "abc" 4384 * StringUtils.join([null, "", "a"], ';') = ";;a" 4385 * </pre> 4386 * 4387 * @param list the {@code List} of values to join together, may be null 4388 * @param separator the separator character to use 4389 * @param startIndex the first index to start joining from. It is 4390 * an error to pass in a start index past the end of the list 4391 * @param endIndex the index to stop joining from (exclusive). It is 4392 * an error to pass in an end index past the end of the list 4393 * @return the joined String, {@code null} if null list input 4394 * @since 3.8 4395 */ 4396 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4397 if (list == null) { 4398 return null; 4399 } 4400 final int noOfItems = endIndex - startIndex; 4401 if (noOfItems <= 0) { 4402 return EMPTY; 4403 } 4404 final List<?> subList = list.subList(startIndex, endIndex); 4405 return join(subList.iterator(), separator); 4406 } 4407 4408 /** 4409 * <p>Joins the elements of the provided {@code List} into a single String 4410 * containing the provided list of elements.</p> 4411 * 4412 * <p>No delimiter is added before or after the list. 4413 * Null objects or empty strings within the array are represented by 4414 * empty strings.</p> 4415 * 4416 * <pre> 4417 * StringUtils.join(null, *) = null 4418 * StringUtils.join([], *) = "" 4419 * StringUtils.join([null], *) = "" 4420 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4421 * StringUtils.join(["a", "b", "c"], null) = "abc" 4422 * StringUtils.join([null, "", "a"], ';') = ";;a" 4423 * </pre> 4424 * 4425 * @param list the {@code List} of values to join together, may be null 4426 * @param separator the separator character to use 4427 * @param startIndex the first index to start joining from. It is 4428 * an error to pass in a start index past the end of the list 4429 * @param endIndex the index to stop joining from (exclusive). It is 4430 * an error to pass in an end index past the end of the list 4431 * @return the joined String, {@code null} if null list input 4432 * @since 3.8 4433 */ 4434 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4435 if (list == null) { 4436 return null; 4437 } 4438 final int noOfItems = endIndex - startIndex; 4439 if (noOfItems <= 0) { 4440 return EMPTY; 4441 } 4442 final List<?> subList = list.subList(startIndex, endIndex); 4443 return join(subList.iterator(), separator); 4444 } 4445 4446 4447 /** 4448 * <p> 4449 * Joins the elements of the provided array into a single String containing the provided list of elements. 4450 * </p> 4451 * 4452 * <p> 4453 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4454 * by empty strings. 4455 * </p> 4456 * 4457 * <pre> 4458 * StringUtils.join(null, *) = null 4459 * StringUtils.join([], *) = "" 4460 * StringUtils.join([null], *) = "" 4461 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4462 * StringUtils.join([1, 2, 3], null) = "123" 4463 * </pre> 4464 * 4465 * @param array 4466 * the array of values to join together, may be null 4467 * @param separator 4468 * the separator character to use 4469 * @return the joined String, {@code null} if null array input 4470 * @since 3.2 4471 */ 4472 public static String join(final long[] array, final char separator) { 4473 if (array == null) { 4474 return null; 4475 } 4476 return join(array, separator, 0, array.length); 4477 } 4478 4479 /** 4480 * <p> 4481 * Joins the elements of the provided array into a single String containing the provided list of elements. 4482 * </p> 4483 * 4484 * <p> 4485 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4486 * by empty strings. 4487 * </p> 4488 * 4489 * <pre> 4490 * StringUtils.join(null, *) = null 4491 * StringUtils.join([], *) = "" 4492 * StringUtils.join([null], *) = "" 4493 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4494 * StringUtils.join([1, 2, 3], null) = "123" 4495 * </pre> 4496 * 4497 * @param array 4498 * the array of values to join together, may be null 4499 * @param separator 4500 * the separator character to use 4501 * @param startIndex 4502 * the first index to start joining from. It is an error to pass in a start index past the end of the 4503 * array 4504 * @param endIndex 4505 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4506 * the array 4507 * @return the joined String, {@code null} if null array input 4508 * @since 3.2 4509 */ 4510 public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) { 4511 if (array == null) { 4512 return null; 4513 } 4514 final int noOfItems = endIndex - startIndex; 4515 if (noOfItems <= 0) { 4516 return EMPTY; 4517 } 4518 final StringBuilder buf = newStringBuilder(noOfItems); 4519 buf.append(array[startIndex]); 4520 for (int i = startIndex + 1; i < endIndex; i++) { 4521 buf.append(separator); 4522 buf.append(array[i]); 4523 } 4524 return buf.toString(); 4525 } 4526 4527 /** 4528 * <p>Joins the elements of the provided array into a single String 4529 * containing the provided list of elements.</p> 4530 * 4531 * <p>No delimiter is added before or after the list. 4532 * Null objects or empty strings within the array are represented by 4533 * empty strings.</p> 4534 * 4535 * <pre> 4536 * StringUtils.join(null, *) = null 4537 * StringUtils.join([], *) = "" 4538 * StringUtils.join([null], *) = "" 4539 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4540 * StringUtils.join(["a", "b", "c"], null) = "abc" 4541 * StringUtils.join([null, "", "a"], ';') = ";;a" 4542 * </pre> 4543 * 4544 * @param array the array of values to join together, may be null 4545 * @param separator the separator character to use 4546 * @return the joined String, {@code null} if null array input 4547 * @since 2.0 4548 */ 4549 public static String join(final Object[] array, final char separator) { 4550 if (array == null) { 4551 return null; 4552 } 4553 return join(array, separator, 0, array.length); 4554 } 4555 4556 /** 4557 * <p>Joins the elements of the provided array into a single String 4558 * containing the provided list of elements.</p> 4559 * 4560 * <p>No delimiter is added before or after the list. 4561 * Null objects or empty strings within the array are represented by 4562 * empty strings.</p> 4563 * 4564 * <pre> 4565 * StringUtils.join(null, *) = null 4566 * StringUtils.join([], *) = "" 4567 * StringUtils.join([null], *) = "" 4568 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4569 * StringUtils.join(["a", "b", "c"], null) = "abc" 4570 * StringUtils.join([null, "", "a"], ';') = ";;a" 4571 * </pre> 4572 * 4573 * @param array the array of values to join together, may be null 4574 * @param separator the separator character to use 4575 * @param startIndex the first index to start joining from. It is 4576 * an error to pass in a start index past the end of the array 4577 * @param endIndex the index to stop joining from (exclusive). It is 4578 * an error to pass in an end index past the end of the array 4579 * @return the joined String, {@code null} if null array input 4580 * @since 2.0 4581 */ 4582 public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) { 4583 if (array == null) { 4584 return null; 4585 } 4586 final int noOfItems = endIndex - startIndex; 4587 if (noOfItems <= 0) { 4588 return EMPTY; 4589 } 4590 final StringBuilder buf = newStringBuilder(noOfItems); 4591 if (array[startIndex] != null) { 4592 buf.append(array[startIndex]); 4593 } 4594 for (int i = startIndex + 1; i < endIndex; i++) { 4595 buf.append(separator); 4596 if (array[i] != null) { 4597 buf.append(array[i]); 4598 } 4599 } 4600 return buf.toString(); 4601 } 4602 4603 /** 4604 * <p>Joins the elements of the provided array into a single String 4605 * containing the provided list of elements.</p> 4606 * 4607 * <p>No delimiter is added before or after the list. 4608 * A {@code null} separator is the same as an empty String (""). 4609 * Null objects or empty strings within the array are represented by 4610 * empty strings.</p> 4611 * 4612 * <pre> 4613 * StringUtils.join(null, *) = null 4614 * StringUtils.join([], *) = "" 4615 * StringUtils.join([null], *) = "" 4616 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 4617 * StringUtils.join(["a", "b", "c"], null) = "abc" 4618 * StringUtils.join(["a", "b", "c"], "") = "abc" 4619 * StringUtils.join([null, "", "a"], ',') = ",,a" 4620 * </pre> 4621 * 4622 * @param array the array of values to join together, may be null 4623 * @param separator the separator character to use, null treated as "" 4624 * @return the joined String, {@code null} if null array input 4625 */ 4626 public static String join(final Object[] array, final String separator) { 4627 if (array == null) { 4628 return null; 4629 } 4630 return join(array, separator, 0, array.length); 4631 } 4632 4633 /** 4634 * <p>Joins the elements of the provided array into a single String 4635 * containing the provided list of elements.</p> 4636 * 4637 * <p>No delimiter is added before or after the list. 4638 * A {@code null} separator is the same as an empty String (""). 4639 * Null objects or empty strings within the array are represented by 4640 * empty strings.</p> 4641 * 4642 * <pre> 4643 * StringUtils.join(null, *, *, *) = null 4644 * StringUtils.join([], *, *, *) = "" 4645 * StringUtils.join([null], *, *, *) = "" 4646 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4647 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4648 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4649 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4650 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4651 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4652 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4653 * </pre> 4654 * 4655 * @param array the array of values to join together, may be null 4656 * @param separator the separator character to use, null treated as "" 4657 * @param startIndex the first index to start joining from. 4658 * @param endIndex the index to stop joining from (exclusive). 4659 * @return the joined String, {@code null} if null array input; or the empty string 4660 * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by 4661 * {@code endIndex - startIndex} 4662 * @throws ArrayIndexOutOfBoundsException ife<br> 4663 * {@code startIndex < 0} or <br> 4664 * {@code startIndex >= array.length()} or <br> 4665 * {@code endIndex < 0} or <br> 4666 * {@code endIndex > array.length()} 4667 */ 4668 public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) { 4669 if (array == null) { 4670 return null; 4671 } 4672 if (separator == null) { 4673 separator = EMPTY; 4674 } 4675 4676 // endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator)) 4677 // (Assuming that all Strings are roughly equally long) 4678 final int noOfItems = endIndex - startIndex; 4679 if (noOfItems <= 0) { 4680 return EMPTY; 4681 } 4682 4683 final StringBuilder buf = newStringBuilder(noOfItems); 4684 4685 if (array[startIndex] != null) { 4686 buf.append(array[startIndex]); 4687 } 4688 4689 for (int i = startIndex + 1; i < endIndex; i++) { 4690 buf.append(separator); 4691 4692 if (array[i] != null) { 4693 buf.append(array[i]); 4694 } 4695 } 4696 return buf.toString(); 4697 } 4698 4699 /** 4700 * <p> 4701 * Joins the elements of the provided array into a single String containing the provided list of elements. 4702 * </p> 4703 * 4704 * <p> 4705 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4706 * by empty strings. 4707 * </p> 4708 * 4709 * <pre> 4710 * StringUtils.join(null, *) = null 4711 * StringUtils.join([], *) = "" 4712 * StringUtils.join([null], *) = "" 4713 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4714 * StringUtils.join([1, 2, 3], null) = "123" 4715 * </pre> 4716 * 4717 * @param array 4718 * the array of values to join together, may be null 4719 * @param separator 4720 * the separator character to use 4721 * @return the joined String, {@code null} if null array input 4722 * @since 3.2 4723 */ 4724 public static String join(final short[] array, final char separator) { 4725 if (array == null) { 4726 return null; 4727 } 4728 return join(array, separator, 0, array.length); 4729 } 4730 4731 /** 4732 * <p> 4733 * Joins the elements of the provided array into a single String containing the provided list of elements. 4734 * </p> 4735 * 4736 * <p> 4737 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4738 * by empty strings. 4739 * </p> 4740 * 4741 * <pre> 4742 * StringUtils.join(null, *) = null 4743 * StringUtils.join([], *) = "" 4744 * StringUtils.join([null], *) = "" 4745 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4746 * StringUtils.join([1, 2, 3], null) = "123" 4747 * </pre> 4748 * 4749 * @param array 4750 * the array of values to join together, may be null 4751 * @param separator 4752 * the separator character to use 4753 * @param startIndex 4754 * the first index to start joining from. It is an error to pass in a start index past the end of the 4755 * array 4756 * @param endIndex 4757 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4758 * the array 4759 * @return the joined String, {@code null} if null array input 4760 * @since 3.2 4761 */ 4762 public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) { 4763 if (array == null) { 4764 return null; 4765 } 4766 final int noOfItems = endIndex - startIndex; 4767 if (noOfItems <= 0) { 4768 return EMPTY; 4769 } 4770 final StringBuilder buf = newStringBuilder(noOfItems); 4771 buf.append(array[startIndex]); 4772 for (int i = startIndex + 1; i < endIndex; i++) { 4773 buf.append(separator); 4774 buf.append(array[i]); 4775 } 4776 return buf.toString(); 4777 } 4778 4779 4780 // Joining 4781 //----------------------------------------------------------------------- 4782 /** 4783 * <p>Joins the elements of the provided array into a single String 4784 * containing the provided list of elements.</p> 4785 * 4786 * <p>No separator is added to the joined String. 4787 * Null objects or empty strings within the array are represented by 4788 * empty strings.</p> 4789 * 4790 * <pre> 4791 * StringUtils.join(null) = null 4792 * StringUtils.join([]) = "" 4793 * StringUtils.join([null]) = "" 4794 * StringUtils.join(["a", "b", "c"]) = "abc" 4795 * StringUtils.join([null, "", "a"]) = "a" 4796 * </pre> 4797 * 4798 * @param <T> the specific type of values to join together 4799 * @param elements the values to join together, may be null 4800 * @return the joined String, {@code null} if null array input 4801 * @since 2.0 4802 * @since 3.0 Changed signature to use varargs 4803 */ 4804 @SafeVarargs 4805 public static <T> String join(final T... elements) { 4806 return join(elements, null); 4807 } 4808 4809 /** 4810 * <p>Joins the elements of the provided varargs into a 4811 * single String containing the provided elements.</p> 4812 * 4813 * <p>No delimiter is added before or after the list. 4814 * {@code null} elements and separator are treated as empty Strings ("").</p> 4815 * 4816 * <pre> 4817 * StringUtils.joinWith(",", {"a", "b"}) = "a,b" 4818 * StringUtils.joinWith(",", {"a", "b",""}) = "a,b," 4819 * StringUtils.joinWith(",", {"a", null, "b"}) = "a,,b" 4820 * StringUtils.joinWith(null, {"a", "b"}) = "ab" 4821 * </pre> 4822 * 4823 * @param separator the separator character to use, null treated as "" 4824 * @param objects the varargs providing the values to join together. {@code null} elements are treated as "" 4825 * @return the joined String. 4826 * @throws java.lang.IllegalArgumentException if a null varargs is provided 4827 * @since 3.5 4828 */ 4829 public static String joinWith(final String separator, final Object... objects) { 4830 if (objects == null) { 4831 throw new IllegalArgumentException("Object varargs must not be null"); 4832 } 4833 4834 final String sanitizedSeparator = defaultString(separator); 4835 4836 final StringBuilder result = new StringBuilder(); 4837 4838 final Iterator<Object> iterator = Arrays.asList(objects).iterator(); 4839 while (iterator.hasNext()) { 4840 final String value = Objects.toString(iterator.next(), ""); 4841 result.append(value); 4842 4843 if (iterator.hasNext()) { 4844 result.append(sanitizedSeparator); 4845 } 4846 } 4847 4848 return result.toString(); 4849 } 4850 4851 /** 4852 * <p>Finds the last index within a CharSequence, handling {@code null}. 4853 * This method uses {@link String#lastIndexOf(String)} if possible.</p> 4854 * 4855 * <p>A {@code null} CharSequence will return {@code -1}.</p> 4856 * 4857 * <pre> 4858 * StringUtils.lastIndexOf(null, *) = -1 4859 * StringUtils.lastIndexOf(*, null) = -1 4860 * StringUtils.lastIndexOf("", "") = 0 4861 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4862 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4863 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4864 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4865 * </pre> 4866 * 4867 * @param seq the CharSequence to check, may be null 4868 * @param searchSeq the CharSequence to find, may be null 4869 * @return the last index of the search String, 4870 * -1 if no match or {@code null} string input 4871 * @since 2.0 4872 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4873 */ 4874 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4875 if (seq == null || searchSeq == null) { 4876 return INDEX_NOT_FOUND; 4877 } 4878 return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length()); 4879 } 4880 4881 /** 4882 * <p>Finds the last index within a CharSequence, handling {@code null}. 4883 * This method uses {@link String#lastIndexOf(String, int)} if possible.</p> 4884 * 4885 * <p>A {@code null} CharSequence will return {@code -1}. 4886 * A negative start position returns {@code -1}. 4887 * An empty ("") search CharSequence always matches unless the start position is negative. 4888 * A start position greater than the string length searches the whole string. 4889 * The search starts at the startPos and works backwards; matches starting after the start 4890 * position are ignored. 4891 * </p> 4892 * 4893 * <pre> 4894 * StringUtils.lastIndexOf(null, *, *) = -1 4895 * StringUtils.lastIndexOf(*, null, *) = -1 4896 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4897 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4898 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4899 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4900 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4901 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4902 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4903 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4904 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4905 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4906 * </pre> 4907 * 4908 * @param seq the CharSequence to check, may be null 4909 * @param searchSeq the CharSequence to find, may be null 4910 * @param startPos the start position, negative treated as zero 4911 * @return the last index of the search CharSequence (always ≤ startPos), 4912 * -1 if no match or {@code null} string input 4913 * @since 2.0 4914 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4915 */ 4916 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4917 if (seq == null || searchSeq == null) { 4918 return INDEX_NOT_FOUND; 4919 } 4920 return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos); 4921 } 4922 4923 // LastIndexOf 4924 //----------------------------------------------------------------------- 4925 /** 4926 * Returns the index within {@code seq} of the last occurrence of 4927 * the specified character. For values of {@code searchChar} in the 4928 * range from 0 to 0xFFFF (inclusive), the index (in Unicode code 4929 * units) returned is the largest value <i>k</i> such that: 4930 * <blockquote><pre> 4931 * this.charAt(<i>k</i>) == searchChar 4932 * </pre></blockquote> 4933 * is true. For other values of {@code searchChar}, it is the 4934 * largest value <i>k</i> such that: 4935 * <blockquote><pre> 4936 * this.codePointAt(<i>k</i>) == searchChar 4937 * </pre></blockquote> 4938 * is true. In either case, if no such character occurs in this 4939 * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4940 * {@code CharSequence} will return {@code -1}. The 4941 * {@code seq} {@code CharSequence} object is searched backwards 4942 * starting at the last character. 4943 * 4944 * <pre> 4945 * StringUtils.lastIndexOf(null, *) = -1 4946 * StringUtils.lastIndexOf("", *) = -1 4947 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4948 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4949 * </pre> 4950 * 4951 * @param seq the {@code CharSequence} to check, may be null 4952 * @param searchChar the character to find 4953 * @return the last index of the search character, 4954 * -1 if no match or {@code null} string input 4955 * @since 2.0 4956 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4957 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String} 4958 */ 4959 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4960 if (isEmpty(seq)) { 4961 return INDEX_NOT_FOUND; 4962 } 4963 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4964 } 4965 4966 /** 4967 * Returns the index within {@code seq} of the last occurrence of 4968 * the specified character, searching backward starting at the 4969 * specified index. For values of {@code searchChar} in the range 4970 * from 0 to 0xFFFF (inclusive), the index returned is the largest 4971 * value <i>k</i> such that: 4972 * <blockquote><pre> 4973 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4974 * </pre></blockquote> 4975 * is true. For other values of {@code searchChar}, it is the 4976 * largest value <i>k</i> such that: 4977 * <blockquote><pre> 4978 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4979 * </pre></blockquote> 4980 * is true. In either case, if no such character occurs in {@code seq} 4981 * at or before position {@code startPos}, then 4982 * {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4983 * {@code CharSequence} will return {@code -1}. A start position greater 4984 * than the string length searches the whole string. 4985 * The search starts at the {@code startPos} and works backwards; 4986 * matches starting after the start position are ignored. 4987 * 4988 * <p>All indices are specified in {@code char} values 4989 * (Unicode code units). 4990 * 4991 * <pre> 4992 * StringUtils.lastIndexOf(null, *, *) = -1 4993 * StringUtils.lastIndexOf("", *, *) = -1 4994 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4995 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4996 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4997 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4998 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 4999 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 5000 * </pre> 5001 * 5002 * @param seq the CharSequence to check, may be null 5003 * @param searchChar the character to find 5004 * @param startPos the start position 5005 * @return the last index of the search character (always ≤ startPos), 5006 * -1 if no match or {@code null} string input 5007 * @since 2.0 5008 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 5009 */ 5010 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 5011 if (isEmpty(seq)) { 5012 return INDEX_NOT_FOUND; 5013 } 5014 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 5015 } 5016 5017 /** 5018 * <p>Find the latest index of any of a set of potential substrings.</p> 5019 * 5020 * <p>A {@code null} CharSequence will return {@code -1}. 5021 * A {@code null} search array will return {@code -1}. 5022 * A {@code null} or zero length search array entry will be ignored, 5023 * but a search array containing "" will return the length of {@code str} 5024 * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p> 5025 * 5026 * <pre> 5027 * StringUtils.lastIndexOfAny(null, *) = -1 5028 * StringUtils.lastIndexOfAny(*, null) = -1 5029 * StringUtils.lastIndexOfAny(*, []) = -1 5030 * StringUtils.lastIndexOfAny(*, [null]) = -1 5031 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 5032 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 5033 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5034 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5035 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 5036 * </pre> 5037 * 5038 * @param str the CharSequence to check, may be null 5039 * @param searchStrs the CharSequences to search for, may be null 5040 * @return the last index of any of the CharSequences, -1 if no match 5041 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 5042 */ 5043 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 5044 if (str == null || searchStrs == null) { 5045 return INDEX_NOT_FOUND; 5046 } 5047 int ret = INDEX_NOT_FOUND; 5048 int tmp = 0; 5049 for (final CharSequence search : searchStrs) { 5050 if (search == null) { 5051 continue; 5052 } 5053 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 5054 if (tmp > ret) { 5055 ret = tmp; 5056 } 5057 } 5058 return ret; 5059 } 5060 5061 /** 5062 * <p>Case in-sensitive find of the last index within a CharSequence.</p> 5063 * 5064 * <p>A {@code null} CharSequence will return {@code -1}. 5065 * A negative start position returns {@code -1}. 5066 * An empty ("") search CharSequence always matches unless the start position is negative. 5067 * A start position greater than the string length searches the whole string.</p> 5068 * 5069 * <pre> 5070 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 5071 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 5072 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 5073 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 5074 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 5075 * </pre> 5076 * 5077 * @param str the CharSequence to check, may be null 5078 * @param searchStr the CharSequence to find, may be null 5079 * @return the first index of the search CharSequence, 5080 * -1 if no match or {@code null} string input 5081 * @since 2.5 5082 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 5083 */ 5084 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 5085 if (str == null || searchStr == null) { 5086 return INDEX_NOT_FOUND; 5087 } 5088 return lastIndexOfIgnoreCase(str, searchStr, str.length()); 5089 } 5090 5091 /** 5092 * <p>Case in-sensitive find of the last index within a CharSequence 5093 * from the specified position.</p> 5094 * 5095 * <p>A {@code null} CharSequence will return {@code -1}. 5096 * A negative start position returns {@code -1}. 5097 * An empty ("") search CharSequence always matches unless the start position is negative. 5098 * A start position greater than the string length searches the whole string. 5099 * The search starts at the startPos and works backwards; matches starting after the start 5100 * position are ignored. 5101 * </p> 5102 * 5103 * <pre> 5104 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 5105 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 5106 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 5107 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 5108 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 5109 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 5110 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 5111 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 5112 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 5113 * </pre> 5114 * 5115 * @param str the CharSequence to check, may be null 5116 * @param searchStr the CharSequence to find, may be null 5117 * @param startPos the start position 5118 * @return the last index of the search CharSequence (always ≤ startPos), 5119 * -1 if no match or {@code null} input 5120 * @since 2.5 5121 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 5122 */ 5123 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 5124 if (str == null || searchStr == null) { 5125 return INDEX_NOT_FOUND; 5126 } 5127 if (startPos > str.length() - searchStr.length()) { 5128 startPos = str.length() - searchStr.length(); 5129 } 5130 if (startPos < 0) { 5131 return INDEX_NOT_FOUND; 5132 } 5133 if (searchStr.length() == 0) { 5134 return startPos; 5135 } 5136 5137 for (int i = startPos; i >= 0; i--) { 5138 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 5139 return i; 5140 } 5141 } 5142 return INDEX_NOT_FOUND; 5143 } 5144 5145 /** 5146 * <p>Finds the n-th last index within a String, handling {@code null}. 5147 * This method uses {@link String#lastIndexOf(String)}.</p> 5148 * 5149 * <p>A {@code null} String will return {@code -1}.</p> 5150 * 5151 * <pre> 5152 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5153 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5154 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5155 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5156 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5157 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5158 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5159 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5160 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5161 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5162 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5163 * </pre> 5164 * 5165 * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p> 5166 * 5167 * <pre> 5168 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5169 * </pre> 5170 * 5171 * @param str the CharSequence to check, may be null 5172 * @param searchStr the CharSequence to find, may be null 5173 * @param ordinal the n-th last {@code searchStr} to find 5174 * @return the n-th last index of the search CharSequence, 5175 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5176 * @since 2.5 5177 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5178 */ 5179 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5180 return ordinalIndexOf(str, searchStr, ordinal, true); 5181 } 5182 5183 // Left/Right/Mid 5184 //----------------------------------------------------------------------- 5185 /** 5186 * <p>Gets the leftmost {@code len} characters of a String.</p> 5187 * 5188 * <p>If {@code len} characters are not available, or the 5189 * String is {@code null}, the String will be returned without 5190 * an exception. An empty String is returned if len is negative.</p> 5191 * 5192 * <pre> 5193 * StringUtils.left(null, *) = null 5194 * StringUtils.left(*, -ve) = "" 5195 * StringUtils.left("", *) = "" 5196 * StringUtils.left("abc", 0) = "" 5197 * StringUtils.left("abc", 2) = "ab" 5198 * StringUtils.left("abc", 4) = "abc" 5199 * </pre> 5200 * 5201 * @param str the String to get the leftmost characters from, may be null 5202 * @param len the length of the required String 5203 * @return the leftmost characters, {@code null} if null String input 5204 */ 5205 public static String left(final String str, final int len) { 5206 if (str == null) { 5207 return null; 5208 } 5209 if (len < 0) { 5210 return EMPTY; 5211 } 5212 if (str.length() <= len) { 5213 return str; 5214 } 5215 return str.substring(0, len); 5216 } 5217 5218 /** 5219 * <p>Left pad a String with spaces (' ').</p> 5220 * 5221 * <p>The String is padded to the size of {@code size}.</p> 5222 * 5223 * <pre> 5224 * StringUtils.leftPad(null, *) = null 5225 * StringUtils.leftPad("", 3) = " " 5226 * StringUtils.leftPad("bat", 3) = "bat" 5227 * StringUtils.leftPad("bat", 5) = " bat" 5228 * StringUtils.leftPad("bat", 1) = "bat" 5229 * StringUtils.leftPad("bat", -1) = "bat" 5230 * </pre> 5231 * 5232 * @param str the String to pad out, may be null 5233 * @param size the size to pad to 5234 * @return left padded String or original String if no padding is necessary, 5235 * {@code null} if null String input 5236 */ 5237 public static String leftPad(final String str, final int size) { 5238 return leftPad(str, size, ' '); 5239 } 5240 5241 /** 5242 * <p>Left pad a String with a specified character.</p> 5243 * 5244 * <p>Pad to a size of {@code size}.</p> 5245 * 5246 * <pre> 5247 * StringUtils.leftPad(null, *, *) = null 5248 * StringUtils.leftPad("", 3, 'z') = "zzz" 5249 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5250 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5251 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5252 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5253 * </pre> 5254 * 5255 * @param str the String to pad out, may be null 5256 * @param size the size to pad to 5257 * @param padChar the character to pad with 5258 * @return left padded String or original String if no padding is necessary, 5259 * {@code null} if null String input 5260 * @since 2.0 5261 */ 5262 public static String leftPad(final String str, final int size, final char padChar) { 5263 if (str == null) { 5264 return null; 5265 } 5266 final int pads = size - str.length(); 5267 if (pads <= 0) { 5268 return str; // returns original String when possible 5269 } 5270 if (pads > PAD_LIMIT) { 5271 return leftPad(str, size, String.valueOf(padChar)); 5272 } 5273 return repeat(padChar, pads).concat(str); 5274 } 5275 5276 /** 5277 * <p>Left pad a String with a specified String.</p> 5278 * 5279 * <p>Pad to a size of {@code size}.</p> 5280 * 5281 * <pre> 5282 * StringUtils.leftPad(null, *, *) = null 5283 * StringUtils.leftPad("", 3, "z") = "zzz" 5284 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5285 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5286 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5287 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5288 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5289 * StringUtils.leftPad("bat", 5, null) = " bat" 5290 * StringUtils.leftPad("bat", 5, "") = " bat" 5291 * </pre> 5292 * 5293 * @param str the String to pad out, may be null 5294 * @param size the size to pad to 5295 * @param padStr the String to pad with, null or empty treated as single space 5296 * @return left padded String or original String if no padding is necessary, 5297 * {@code null} if null String input 5298 */ 5299 public static String leftPad(final String str, final int size, String padStr) { 5300 if (str == null) { 5301 return null; 5302 } 5303 if (isEmpty(padStr)) { 5304 padStr = SPACE; 5305 } 5306 final int padLen = padStr.length(); 5307 final int strLen = str.length(); 5308 final int pads = size - strLen; 5309 if (pads <= 0) { 5310 return str; // returns original String when possible 5311 } 5312 if (padLen == 1 && pads <= PAD_LIMIT) { 5313 return leftPad(str, size, padStr.charAt(0)); 5314 } 5315 5316 if (pads == padLen) { 5317 return padStr.concat(str); 5318 } else if (pads < padLen) { 5319 return padStr.substring(0, pads).concat(str); 5320 } else { 5321 final char[] padding = new char[pads]; 5322 final char[] padChars = padStr.toCharArray(); 5323 for (int i = 0; i < pads; i++) { 5324 padding[i] = padChars[i % padLen]; 5325 } 5326 return new String(padding).concat(str); 5327 } 5328 } 5329 5330 /** 5331 * Gets a CharSequence length or {@code 0} if the CharSequence is 5332 * {@code null}. 5333 * 5334 * @param cs 5335 * a CharSequence or {@code null} 5336 * @return CharSequence length or {@code 0} if the CharSequence is 5337 * {@code null}. 5338 * @since 2.4 5339 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5340 */ 5341 public static int length(final CharSequence cs) { 5342 return cs == null ? 0 : cs.length(); 5343 } 5344 5345 /** 5346 * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p> 5347 * 5348 * <p>A {@code null} input String returns {@code null}.</p> 5349 * 5350 * <pre> 5351 * StringUtils.lowerCase(null) = null 5352 * StringUtils.lowerCase("") = "" 5353 * StringUtils.lowerCase("aBc") = "abc" 5354 * </pre> 5355 * 5356 * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, 5357 * the result of this method is affected by the current locale. 5358 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 5359 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 5360 * 5361 * @param str the String to lower case, may be null 5362 * @return the lower cased String, {@code null} if null String input 5363 */ 5364 public static String lowerCase(final String str) { 5365 if (str == null) { 5366 return null; 5367 } 5368 return str.toLowerCase(); 5369 } 5370 5371 /** 5372 * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p> 5373 * 5374 * <p>A {@code null} input String returns {@code null}.</p> 5375 * 5376 * <pre> 5377 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5378 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5379 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5380 * </pre> 5381 * 5382 * @param str the String to lower case, may be null 5383 * @param locale the locale that defines the case transformation rules, must not be null 5384 * @return the lower cased String, {@code null} if null String input 5385 * @since 2.5 5386 */ 5387 public static String lowerCase(final String str, final Locale locale) { 5388 if (str == null) { 5389 return null; 5390 } 5391 return str.toLowerCase(locale); 5392 } 5393 5394 private static int[] matches(final CharSequence first, final CharSequence second) { 5395 CharSequence max, min; 5396 if (first.length() > second.length()) { 5397 max = first; 5398 min = second; 5399 } else { 5400 max = second; 5401 min = first; 5402 } 5403 final int range = Math.max(max.length() / 2 - 1, 0); 5404 final int[] matchIndexes = new int[min.length()]; 5405 Arrays.fill(matchIndexes, -1); 5406 final boolean[] matchFlags = new boolean[max.length()]; 5407 int matches = 0; 5408 for (int mi = 0; mi < min.length(); mi++) { 5409 final char c1 = min.charAt(mi); 5410 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5411 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5412 matchIndexes[mi] = xi; 5413 matchFlags[xi] = true; 5414 matches++; 5415 break; 5416 } 5417 } 5418 } 5419 final char[] ms1 = new char[matches]; 5420 final char[] ms2 = new char[matches]; 5421 for (int i = 0, si = 0; i < min.length(); i++) { 5422 if (matchIndexes[i] != -1) { 5423 ms1[si] = min.charAt(i); 5424 si++; 5425 } 5426 } 5427 for (int i = 0, si = 0; i < max.length(); i++) { 5428 if (matchFlags[i]) { 5429 ms2[si] = max.charAt(i); 5430 si++; 5431 } 5432 } 5433 int transpositions = 0; 5434 for (int mi = 0; mi < ms1.length; mi++) { 5435 if (ms1[mi] != ms2[mi]) { 5436 transpositions++; 5437 } 5438 } 5439 int prefix = 0; 5440 for (int mi = 0; mi < min.length(); mi++) { 5441 if (first.charAt(mi) == second.charAt(mi)) { 5442 prefix++; 5443 } else { 5444 break; 5445 } 5446 } 5447 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5448 } 5449 5450 /** 5451 * <p>Gets {@code len} characters from the middle of a String.</p> 5452 * 5453 * <p>If {@code len} characters are not available, the remainder 5454 * of the String will be returned without an exception. If the 5455 * String is {@code null}, {@code null} will be returned. 5456 * An empty String is returned if len is negative or exceeds the 5457 * length of {@code str}.</p> 5458 * 5459 * <pre> 5460 * StringUtils.mid(null, *, *) = null 5461 * StringUtils.mid(*, *, -ve) = "" 5462 * StringUtils.mid("", 0, *) = "" 5463 * StringUtils.mid("abc", 0, 2) = "ab" 5464 * StringUtils.mid("abc", 0, 4) = "abc" 5465 * StringUtils.mid("abc", 2, 4) = "c" 5466 * StringUtils.mid("abc", 4, 2) = "" 5467 * StringUtils.mid("abc", -2, 2) = "ab" 5468 * </pre> 5469 * 5470 * @param str the String to get the characters from, may be null 5471 * @param pos the position to start from, negative treated as zero 5472 * @param len the length of the required String 5473 * @return the middle characters, {@code null} if null String input 5474 */ 5475 public static String mid(final String str, int pos, final int len) { 5476 if (str == null) { 5477 return null; 5478 } 5479 if (len < 0 || pos > str.length()) { 5480 return EMPTY; 5481 } 5482 if (pos < 0) { 5483 pos = 0; 5484 } 5485 if (str.length() <= pos + len) { 5486 return str.substring(pos); 5487 } 5488 return str.substring(pos, pos + len); 5489 } 5490 5491 private static StringBuilder newStringBuilder(final int noOfItems) { 5492 return new StringBuilder(noOfItems * 16); 5493 } 5494 5495 /** 5496 * <p> 5497 * Similar to <a 5498 * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize 5499 * -space</a> 5500 * </p> 5501 * <p> 5502 * The function returns the argument string with whitespace normalized by using 5503 * {@code {@link #trim(String)}} to remove leading and trailing whitespace 5504 * and then replacing sequences of whitespace characters by a single space. 5505 * </p> 5506 * In XML Whitespace characters are the same as those allowed by the <a 5507 * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+ 5508 * <p> 5509 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 5510 * 5511 * <p>For reference:</p> 5512 * <ul> 5513 * <li>\x0B = vertical tab</li> 5514 * <li>\f = #xC = form feed</li> 5515 * <li>#x20 = space</li> 5516 * <li>#x9 = \t</li> 5517 * <li>#xA = \n</li> 5518 * <li>#xD = \r</li> 5519 * </ul> 5520 * 5521 * <p> 5522 * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also 5523 * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char <= 32) from both 5524 * ends of this String. 5525 * </p> 5526 * 5527 * @see Pattern 5528 * @see #trim(String) 5529 * @see <a 5530 * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize-space</a> 5531 * @param str the source String to normalize whitespaces from, may be null 5532 * @return the modified string with whitespace normalized, {@code null} if null String input 5533 * 5534 * @since 3.0 5535 */ 5536 public static String normalizeSpace(final String str) { 5537 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5538 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5539 if (isEmpty(str)) { 5540 return str; 5541 } 5542 final int size = str.length(); 5543 final char[] newChars = new char[size]; 5544 int count = 0; 5545 int whitespacesCount = 0; 5546 boolean startWhitespaces = true; 5547 for (int i = 0; i < size; i++) { 5548 final char actualChar = str.charAt(i); 5549 final boolean isWhitespace = Character.isWhitespace(actualChar); 5550 if (isWhitespace) { 5551 if (whitespacesCount == 0 && !startWhitespaces) { 5552 newChars[count++] = SPACE.charAt(0); 5553 } 5554 whitespacesCount++; 5555 } else { 5556 startWhitespaces = false; 5557 newChars[count++] = (actualChar == 160 ? 32 : actualChar); 5558 whitespacesCount = 0; 5559 } 5560 } 5561 if (startWhitespaces) { 5562 return EMPTY; 5563 } 5564 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5565 } 5566 5567 /** 5568 * <p>Finds the n-th index within a CharSequence, handling {@code null}. 5569 * This method uses {@link String#indexOf(String)} if possible.</p> 5570 * <p><b>Note:</b> The code starts looking for a match at the start of the target, 5571 * incrementing the starting index by one after each successful match 5572 * (unless {@code searchStr} is an empty string in which case the position 5573 * is never incremented and {@code 0} is returned immediately). 5574 * This means that matches may overlap.</p> 5575 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5576 * 5577 * <pre> 5578 * StringUtils.ordinalIndexOf(null, *, *) = -1 5579 * StringUtils.ordinalIndexOf(*, null, *) = -1 5580 * StringUtils.ordinalIndexOf("", "", *) = 0 5581 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5582 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5583 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5584 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5585 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5586 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5587 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5588 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5589 * </pre> 5590 * 5591 * <p>Matches may overlap:</p> 5592 * <pre> 5593 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5594 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5595 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5596 * 5597 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5598 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5599 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5600 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5601 * </pre> 5602 * 5603 * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p> 5604 * 5605 * <pre> 5606 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5607 * </pre> 5608 * 5609 * @param str the CharSequence to check, may be null 5610 * @param searchStr the CharSequence to find, may be null 5611 * @param ordinal the n-th {@code searchStr} to find 5612 * @return the n-th index of the search CharSequence, 5613 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5614 * @since 2.1 5615 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5616 */ 5617 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5618 return ordinalIndexOf(str, searchStr, ordinal, false); 5619 } 5620 5621 /** 5622 * <p>Finds the n-th index within a String, handling {@code null}. 5623 * This method uses {@link String#indexOf(String)} if possible.</p> 5624 * <p>Note that matches may overlap<p> 5625 * 5626 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5627 * 5628 * @param str the CharSequence to check, may be null 5629 * @param searchStr the CharSequence to find, may be null 5630 * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed. 5631 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf() 5632 * @return the n-th index of the search CharSequence, 5633 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5634 */ 5635 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5636 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5637 if (str == null || searchStr == null || ordinal <= 0) { 5638 return INDEX_NOT_FOUND; 5639 } 5640 if (searchStr.length() == 0) { 5641 return lastIndex ? str.length() : 0; 5642 } 5643 int found = 0; 5644 // set the initial index beyond the end of the string 5645 // this is to allow for the initial index decrement/increment 5646 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5647 do { 5648 if (lastIndex) { 5649 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards thru string 5650 } else { 5651 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5652 } 5653 if (index < 0) { 5654 return index; 5655 } 5656 found++; 5657 } while (found < ordinal); 5658 return index; 5659 } 5660 5661 // Overlay 5662 //----------------------------------------------------------------------- 5663 /** 5664 * <p>Overlays part of a String with another String.</p> 5665 * 5666 * <p>A {@code null} string input returns {@code null}. 5667 * A negative index is treated as zero. 5668 * An index greater than the string length is treated as the string length. 5669 * The start index is always the smaller of the two indices.</p> 5670 * 5671 * <pre> 5672 * StringUtils.overlay(null, *, *, *) = null 5673 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5674 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5675 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5676 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5677 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5678 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5679 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5680 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5681 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5682 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5683 * </pre> 5684 * 5685 * @param str the String to do overlaying in, may be null 5686 * @param overlay the String to overlay, may be null 5687 * @param start the position to start overlaying at 5688 * @param end the position to stop overlaying before 5689 * @return overlayed String, {@code null} if null String input 5690 * @since 2.0 5691 */ 5692 public static String overlay(final String str, String overlay, int start, int end) { 5693 if (str == null) { 5694 return null; 5695 } 5696 if (overlay == null) { 5697 overlay = EMPTY; 5698 } 5699 final int len = str.length(); 5700 if (start < 0) { 5701 start = 0; 5702 } 5703 if (start > len) { 5704 start = len; 5705 } 5706 if (end < 0) { 5707 end = 0; 5708 } 5709 if (end > len) { 5710 end = len; 5711 } 5712 if (start > end) { 5713 final int temp = start; 5714 start = end; 5715 end = temp; 5716 } 5717 return str.substring(0, start) + 5718 overlay + 5719 str.substring(end); 5720 } 5721 5722 /** 5723 * Prepends the prefix to the start of the string if the string does not 5724 * already start with any of the prefixes. 5725 * 5726 * @param str The string. 5727 * @param prefix The prefix to prepend to the start of the string. 5728 * @param ignoreCase Indicates whether the compare should ignore case. 5729 * @param prefixes Additional prefixes that are valid (optional). 5730 * 5731 * @return A new String if prefix was prepended, the same string otherwise. 5732 */ 5733 private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) { 5734 if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) { 5735 return str; 5736 } 5737 if (ArrayUtils.isNotEmpty(prefixes)) { 5738 for (final CharSequence p : prefixes) { 5739 if (startsWith(str, p, ignoreCase)) { 5740 return str; 5741 } 5742 } 5743 } 5744 return prefix.toString() + str; 5745 } 5746 5747 /** 5748 * Prepends the prefix to the start of the string if the string does not 5749 * already start with any of the prefixes. 5750 * 5751 * <pre> 5752 * StringUtils.prependIfMissing(null, null) = null 5753 * StringUtils.prependIfMissing("abc", null) = "abc" 5754 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5755 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5756 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5757 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5758 * </pre> 5759 * <p>With additional prefixes,</p> 5760 * <pre> 5761 * StringUtils.prependIfMissing(null, null, null) = null 5762 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5763 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5764 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5765 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5766 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5767 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5768 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5769 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5770 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5771 * </pre> 5772 * 5773 * @param str The string. 5774 * @param prefix The prefix to prepend to the start of the string. 5775 * @param prefixes Additional prefixes that are valid. 5776 * 5777 * @return A new String if prefix was prepended, the same string otherwise. 5778 * 5779 * @since 3.2 5780 */ 5781 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5782 return prependIfMissing(str, prefix, false, prefixes); 5783 } 5784 5785 /** 5786 * Prepends the prefix to the start of the string if the string does not 5787 * already start, case insensitive, with any of the prefixes. 5788 * 5789 * <pre> 5790 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5791 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5792 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5793 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5794 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5795 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5796 * </pre> 5797 * <p>With additional prefixes,</p> 5798 * <pre> 5799 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5800 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5801 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5802 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5803 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5804 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5805 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5806 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5807 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5808 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5809 * </pre> 5810 * 5811 * @param str The string. 5812 * @param prefix The prefix to prepend to the start of the string. 5813 * @param prefixes Additional prefixes that are valid (optional). 5814 * 5815 * @return A new String if prefix was prepended, the same string otherwise. 5816 * 5817 * @since 3.2 5818 */ 5819 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5820 return prependIfMissing(str, prefix, true, prefixes); 5821 } 5822 5823 /** 5824 * <p>Removes all occurrences of a character from within the source string.</p> 5825 * 5826 * <p>A {@code null} source string will return {@code null}. 5827 * An empty ("") source string will return the empty string.</p> 5828 * 5829 * <pre> 5830 * StringUtils.remove(null, *) = null 5831 * StringUtils.remove("", *) = "" 5832 * StringUtils.remove("queued", 'u') = "qeed" 5833 * StringUtils.remove("queued", 'z') = "queued" 5834 * </pre> 5835 * 5836 * @param str the source String to search, may be null 5837 * @param remove the char to search for and remove, may be null 5838 * @return the substring with the char removed if found, 5839 * {@code null} if null String input 5840 * @since 2.1 5841 */ 5842 public static String remove(final String str, final char remove) { 5843 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5844 return str; 5845 } 5846 final char[] chars = str.toCharArray(); 5847 int pos = 0; 5848 for (int i = 0; i < chars.length; i++) { 5849 if (chars[i] != remove) { 5850 chars[pos++] = chars[i]; 5851 } 5852 } 5853 return new String(chars, 0, pos); 5854 } 5855 5856 /** 5857 * <p>Removes all occurrences of a substring from within the source string.</p> 5858 * 5859 * <p>A {@code null} source string will return {@code null}. 5860 * An empty ("") source string will return the empty string. 5861 * A {@code null} remove string will return the source string. 5862 * An empty ("") remove string will return the source string.</p> 5863 * 5864 * <pre> 5865 * StringUtils.remove(null, *) = null 5866 * StringUtils.remove("", *) = "" 5867 * StringUtils.remove(*, null) = * 5868 * StringUtils.remove(*, "") = * 5869 * StringUtils.remove("queued", "ue") = "qd" 5870 * StringUtils.remove("queued", "zz") = "queued" 5871 * </pre> 5872 * 5873 * @param str the source String to search, may be null 5874 * @param remove the String to search for and remove, may be null 5875 * @return the substring with the string removed if found, 5876 * {@code null} if null String input 5877 * @since 2.1 5878 */ 5879 public static String remove(final String str, final String remove) { 5880 if (isEmpty(str) || isEmpty(remove)) { 5881 return str; 5882 } 5883 return replace(str, remove, EMPTY, -1); 5884 } 5885 5886 /** 5887 * <p>Removes each substring of the text String that matches the given regular expression.</p> 5888 * 5889 * This method is a {@code null} safe equivalent to: 5890 * <ul> 5891 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5892 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5893 * </ul> 5894 * 5895 * <p>A {@code null} reference passed to this method is a no-op.</p> 5896 * 5897 * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option 5898 * is NOT automatically added. 5899 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 5900 * DOTALL is also known as single-line mode in Perl.</p> 5901 * 5902 * <pre> 5903 * StringUtils.removeAll(null, *) = null 5904 * StringUtils.removeAll("any", (String) null) = "any" 5905 * StringUtils.removeAll("any", "") = "any" 5906 * StringUtils.removeAll("any", ".*") = "" 5907 * StringUtils.removeAll("any", ".+") = "" 5908 * StringUtils.removeAll("abc", ".?") = "" 5909 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5910 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5911 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5912 * </pre> 5913 * 5914 * @param text text to remove from, may be null 5915 * @param regex the regular expression to which this string is to be matched 5916 * @return the text with any removes processed, 5917 * {@code null} if null String input 5918 * 5919 * @throws java.util.regex.PatternSyntaxException 5920 * if the regular expression's syntax is invalid 5921 * 5922 * @see #replaceAll(String, String, String) 5923 * @see #removePattern(String, String) 5924 * @see String#replaceAll(String, String) 5925 * @see java.util.regex.Pattern 5926 * @see java.util.regex.Pattern#DOTALL 5927 * @since 3.5 5928 * 5929 * @deprecated Moved to RegExUtils. 5930 */ 5931 @Deprecated 5932 public static String removeAll(final String text, final String regex) { 5933 return RegExUtils.removeAll(text, regex); 5934 } 5935 5936 /** 5937 * <p>Removes a substring only if it is at the end of a source string, 5938 * otherwise returns the source string.</p> 5939 * 5940 * <p>A {@code null} source string will return {@code null}. 5941 * An empty ("") source string will return the empty string. 5942 * A {@code null} search string will return the source string.</p> 5943 * 5944 * <pre> 5945 * StringUtils.removeEnd(null, *) = null 5946 * StringUtils.removeEnd("", *) = "" 5947 * StringUtils.removeEnd(*, null) = * 5948 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5949 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5950 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5951 * StringUtils.removeEnd("abc", "") = "abc" 5952 * </pre> 5953 * 5954 * @param str the source String to search, may be null 5955 * @param remove the String to search for and remove, may be null 5956 * @return the substring with the string removed if found, 5957 * {@code null} if null String input 5958 * @since 2.1 5959 */ 5960 public static String removeEnd(final String str, final String remove) { 5961 if (isEmpty(str) || isEmpty(remove)) { 5962 return str; 5963 } 5964 if (str.endsWith(remove)) { 5965 return str.substring(0, str.length() - remove.length()); 5966 } 5967 return str; 5968 } 5969 5970 /** 5971 * <p>Case insensitive removal of a substring if it is at the end of a source string, 5972 * otherwise returns the source string.</p> 5973 * 5974 * <p>A {@code null} source string will return {@code null}. 5975 * An empty ("") source string will return the empty string. 5976 * A {@code null} search string will return the source string.</p> 5977 * 5978 * <pre> 5979 * StringUtils.removeEndIgnoreCase(null, *) = null 5980 * StringUtils.removeEndIgnoreCase("", *) = "" 5981 * StringUtils.removeEndIgnoreCase(*, null) = * 5982 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5983 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5984 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5985 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5986 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain") 5987 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain") 5988 * </pre> 5989 * 5990 * @param str the source String to search, may be null 5991 * @param remove the String to search for (case insensitive) and remove, may be null 5992 * @return the substring with the string removed if found, 5993 * {@code null} if null String input 5994 * @since 2.4 5995 */ 5996 public static String removeEndIgnoreCase(final String str, final String remove) { 5997 if (isEmpty(str) || isEmpty(remove)) { 5998 return str; 5999 } 6000 if (endsWithIgnoreCase(str, remove)) { 6001 return str.substring(0, str.length() - remove.length()); 6002 } 6003 return str; 6004 } 6005 6006 /** 6007 * <p>Removes the first substring of the text string that matches the given regular expression.</p> 6008 * 6009 * This method is a {@code null} safe equivalent to: 6010 * <ul> 6011 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 6012 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 6013 * </ul> 6014 * 6015 * <p>A {@code null} reference passed to this method is a no-op.</p> 6016 * 6017 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 6018 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6019 * DOTALL is also known as single-line mode in Perl.</p> 6020 * 6021 * <pre> 6022 * StringUtils.removeFirst(null, *) = null 6023 * StringUtils.removeFirst("any", (String) null) = "any" 6024 * StringUtils.removeFirst("any", "") = "any" 6025 * StringUtils.removeFirst("any", ".*") = "" 6026 * StringUtils.removeFirst("any", ".+") = "" 6027 * StringUtils.removeFirst("abc", ".?") = "bc" 6028 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 6029 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 6030 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 6031 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 6032 * </pre> 6033 * 6034 * @param text text to remove from, may be null 6035 * @param regex the regular expression to which this string is to be matched 6036 * @return the text with the first replacement processed, 6037 * {@code null} if null String input 6038 * 6039 * @throws java.util.regex.PatternSyntaxException 6040 * if the regular expression's syntax is invalid 6041 * 6042 * @see #replaceFirst(String, String, String) 6043 * @see String#replaceFirst(String, String) 6044 * @see java.util.regex.Pattern 6045 * @see java.util.regex.Pattern#DOTALL 6046 * @since 3.5 6047 * 6048 * @deprecated Moved to RegExUtils. 6049 */ 6050 @Deprecated 6051 public static String removeFirst(final String text, final String regex) { 6052 return replaceFirst(text, regex, EMPTY); 6053 } 6054 6055 /** 6056 * <p> 6057 * Case insensitive removal of all occurrences of a substring from within 6058 * the source string. 6059 * </p> 6060 * 6061 * <p> 6062 * A {@code null} source string will return {@code null}. An empty ("") 6063 * source string will return the empty string. A {@code null} remove string 6064 * will return the source string. An empty ("") remove string will return 6065 * the source string. 6066 * </p> 6067 * 6068 * <pre> 6069 * StringUtils.removeIgnoreCase(null, *) = null 6070 * StringUtils.removeIgnoreCase("", *) = "" 6071 * StringUtils.removeIgnoreCase(*, null) = * 6072 * StringUtils.removeIgnoreCase(*, "") = * 6073 * StringUtils.removeIgnoreCase("queued", "ue") = "qd" 6074 * StringUtils.removeIgnoreCase("queued", "zz") = "queued" 6075 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd" 6076 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued" 6077 * </pre> 6078 * 6079 * @param str 6080 * the source String to search, may be null 6081 * @param remove 6082 * the String to search for (case insensitive) and remove, may be 6083 * null 6084 * @return the substring with the string removed if found, {@code null} if 6085 * null String input 6086 * @since 3.5 6087 */ 6088 public static String removeIgnoreCase(final String str, final String remove) { 6089 if (isEmpty(str) || isEmpty(remove)) { 6090 return str; 6091 } 6092 return replaceIgnoreCase(str, remove, EMPTY, -1); 6093 } 6094 6095 /** 6096 * <p>Removes each substring of the source String that matches the given regular expression using the DOTALL option. 6097 * </p> 6098 * 6099 * This call is a {@code null} safe equivalent to: 6100 * <ul> 6101 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 6102 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 6103 * </ul> 6104 * 6105 * <p>A {@code null} reference passed to this method is a no-op.</p> 6106 * 6107 * <pre> 6108 * StringUtils.removePattern(null, *) = null 6109 * StringUtils.removePattern("any", (String) null) = "any" 6110 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 6111 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 6112 * </pre> 6113 * 6114 * @param source 6115 * the source string 6116 * @param regex 6117 * the regular expression to which this string is to be matched 6118 * @return The resulting {@code String} 6119 * @see #replacePattern(String, String, String) 6120 * @see String#replaceAll(String, String) 6121 * @see Pattern#DOTALL 6122 * @since 3.2 6123 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6124 * 6125 * @deprecated Moved to RegExUtils. 6126 */ 6127 @Deprecated 6128 public static String removePattern(final String source, final String regex) { 6129 return RegExUtils.removePattern(source, regex); 6130 } 6131 6132 // Remove 6133 //----------------------------------------------------------------------- 6134 /** 6135 * <p>Removes a substring only if it is at the beginning of a source string, 6136 * otherwise returns the source string.</p> 6137 * 6138 * <p>A {@code null} source string will return {@code null}. 6139 * An empty ("") source string will return the empty string. 6140 * A {@code null} search string will return the source string.</p> 6141 * 6142 * <pre> 6143 * StringUtils.removeStart(null, *) = null 6144 * StringUtils.removeStart("", *) = "" 6145 * StringUtils.removeStart(*, null) = * 6146 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 6147 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 6148 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 6149 * StringUtils.removeStart("abc", "") = "abc" 6150 * </pre> 6151 * 6152 * @param str the source String to search, may be null 6153 * @param remove the String to search for and remove, may be null 6154 * @return the substring with the string removed if found, 6155 * {@code null} if null String input 6156 * @since 2.1 6157 */ 6158 public static String removeStart(final String str, final String remove) { 6159 if (isEmpty(str) || isEmpty(remove)) { 6160 return str; 6161 } 6162 if (str.startsWith(remove)) { 6163 return str.substring(remove.length()); 6164 } 6165 return str; 6166 } 6167 6168 /** 6169 * <p>Case insensitive removal of a substring if it is at the beginning of a source string, 6170 * otherwise returns the source string.</p> 6171 * 6172 * <p>A {@code null} source string will return {@code null}. 6173 * An empty ("") source string will return the empty string. 6174 * A {@code null} search string will return the source string.</p> 6175 * 6176 * <pre> 6177 * StringUtils.removeStartIgnoreCase(null, *) = null 6178 * StringUtils.removeStartIgnoreCase("", *) = "" 6179 * StringUtils.removeStartIgnoreCase(*, null) = * 6180 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6181 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6182 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6183 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6184 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6185 * </pre> 6186 * 6187 * @param str the source String to search, may be null 6188 * @param remove the String to search for (case insensitive) and remove, may be null 6189 * @return the substring with the string removed if found, 6190 * {@code null} if null String input 6191 * @since 2.4 6192 */ 6193 public static String removeStartIgnoreCase(final String str, final String remove) { 6194 if (isEmpty(str) || isEmpty(remove)) { 6195 return str; 6196 } 6197 if (startsWithIgnoreCase(str, remove)) { 6198 return str.substring(remove.length()); 6199 } 6200 return str; 6201 } 6202 6203 /** 6204 * <p>Returns padding using the specified delimiter repeated 6205 * to a given length.</p> 6206 * 6207 * <pre> 6208 * StringUtils.repeat('e', 0) = "" 6209 * StringUtils.repeat('e', 3) = "eee" 6210 * StringUtils.repeat('e', -2) = "" 6211 * </pre> 6212 * 6213 * <p>Note: this method does not support padding with 6214 * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6215 * as they require a pair of {@code char}s to be represented. 6216 * If you are needing to support full I18N of your applications 6217 * consider using {@link #repeat(String, int)} instead. 6218 * </p> 6219 * 6220 * @param ch character to repeat 6221 * @param repeat number of times to repeat char, negative treated as zero 6222 * @return String with repeated character 6223 * @see #repeat(String, int) 6224 */ 6225 public static String repeat(final char ch, final int repeat) { 6226 if (repeat <= 0) { 6227 return EMPTY; 6228 } 6229 final char[] buf = new char[repeat]; 6230 for (int i = repeat - 1; i >= 0; i--) { 6231 buf[i] = ch; 6232 } 6233 return new String(buf); 6234 } 6235 6236 // Padding 6237 //----------------------------------------------------------------------- 6238 /** 6239 * <p>Repeat a String {@code repeat} times to form a 6240 * new String.</p> 6241 * 6242 * <pre> 6243 * StringUtils.repeat(null, 2) = null 6244 * StringUtils.repeat("", 0) = "" 6245 * StringUtils.repeat("", 2) = "" 6246 * StringUtils.repeat("a", 3) = "aaa" 6247 * StringUtils.repeat("ab", 2) = "abab" 6248 * StringUtils.repeat("a", -2) = "" 6249 * </pre> 6250 * 6251 * @param str the String to repeat, may be null 6252 * @param repeat number of times to repeat str, negative treated as zero 6253 * @return a new String consisting of the original String repeated, 6254 * {@code null} if null String input 6255 */ 6256 public static String repeat(final String str, final int repeat) { 6257 // Performance tuned for 2.0 (JDK1.4) 6258 6259 if (str == null) { 6260 return null; 6261 } 6262 if (repeat <= 0) { 6263 return EMPTY; 6264 } 6265 final int inputLength = str.length(); 6266 if (repeat == 1 || inputLength == 0) { 6267 return str; 6268 } 6269 if (inputLength == 1 && repeat <= PAD_LIMIT) { 6270 return repeat(str.charAt(0), repeat); 6271 } 6272 6273 final int outputLength = inputLength * repeat; 6274 switch (inputLength) { 6275 case 1 : 6276 return repeat(str.charAt(0), repeat); 6277 case 2 : 6278 final char ch0 = str.charAt(0); 6279 final char ch1 = str.charAt(1); 6280 final char[] output2 = new char[outputLength]; 6281 for (int i = repeat * 2 - 2; i >= 0; i--, i--) { 6282 output2[i] = ch0; 6283 output2[i + 1] = ch1; 6284 } 6285 return new String(output2); 6286 default : 6287 final StringBuilder buf = new StringBuilder(outputLength); 6288 for (int i = 0; i < repeat; i++) { 6289 buf.append(str); 6290 } 6291 return buf.toString(); 6292 } 6293 } 6294 6295 // Conversion 6296 //----------------------------------------------------------------------- 6297 6298 /** 6299 * <p>Repeat a String {@code repeat} times to form a 6300 * new String, with a String separator injected each time. </p> 6301 * 6302 * <pre> 6303 * StringUtils.repeat(null, null, 2) = null 6304 * StringUtils.repeat(null, "x", 2) = null 6305 * StringUtils.repeat("", null, 0) = "" 6306 * StringUtils.repeat("", "", 2) = "" 6307 * StringUtils.repeat("", "x", 3) = "xxx" 6308 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6309 * </pre> 6310 * 6311 * @param str the String to repeat, may be null 6312 * @param separator the String to inject, may be null 6313 * @param repeat number of times to repeat str, negative treated as zero 6314 * @return a new String consisting of the original String repeated, 6315 * {@code null} if null String input 6316 * @since 2.5 6317 */ 6318 public static String repeat(final String str, final String separator, final int repeat) { 6319 if (str == null || separator == null) { 6320 return repeat(str, repeat); 6321 } 6322 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6323 final String result = repeat(str + separator, repeat); 6324 return removeEnd(result, separator); 6325 } 6326 6327 /** 6328 * <p>Replaces all occurrences of a String within another String.</p> 6329 * 6330 * <p>A {@code null} reference passed to this method is a no-op.</p> 6331 * 6332 * <pre> 6333 * StringUtils.replace(null, *, *) = null 6334 * StringUtils.replace("", *, *) = "" 6335 * StringUtils.replace("any", null, *) = "any" 6336 * StringUtils.replace("any", *, null) = "any" 6337 * StringUtils.replace("any", "", *) = "any" 6338 * StringUtils.replace("aba", "a", null) = "aba" 6339 * StringUtils.replace("aba", "a", "") = "b" 6340 * StringUtils.replace("aba", "a", "z") = "zbz" 6341 * </pre> 6342 * 6343 * @see #replace(String text, String searchString, String replacement, int max) 6344 * @param text text to search and replace in, may be null 6345 * @param searchString the String to search for, may be null 6346 * @param replacement the String to replace it with, may be null 6347 * @return the text with any replacements processed, 6348 * {@code null} if null String input 6349 */ 6350 public static String replace(final String text, final String searchString, final String replacement) { 6351 return replace(text, searchString, replacement, -1); 6352 } 6353 6354 /** 6355 * <p>Replaces a String with another String inside a larger String, 6356 * for the first {@code max} values of the search String.</p> 6357 * 6358 * <p>A {@code null} reference passed to this method is a no-op.</p> 6359 * 6360 * <pre> 6361 * StringUtils.replace(null, *, *, *) = null 6362 * StringUtils.replace("", *, *, *) = "" 6363 * StringUtils.replace("any", null, *, *) = "any" 6364 * StringUtils.replace("any", *, null, *) = "any" 6365 * StringUtils.replace("any", "", *, *) = "any" 6366 * StringUtils.replace("any", *, *, 0) = "any" 6367 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6368 * StringUtils.replace("abaa", "a", "", -1) = "b" 6369 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6370 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6371 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6372 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6373 * </pre> 6374 * 6375 * @param text text to search and replace in, may be null 6376 * @param searchString the String to search for, may be null 6377 * @param replacement the String to replace it with, may be null 6378 * @param max maximum number of values to replace, or {@code -1} if no maximum 6379 * @return the text with any replacements processed, 6380 * {@code null} if null String input 6381 */ 6382 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6383 return replace(text, searchString, replacement, max, false); 6384 } 6385 6386 /** 6387 * <p>Replaces a String with another String inside a larger String, 6388 * for the first {@code max} values of the search String, 6389 * case sensitively/insensisitively based on {@code ignoreCase} value.</p> 6390 * 6391 * <p>A {@code null} reference passed to this method is a no-op.</p> 6392 * 6393 * <pre> 6394 * StringUtils.replace(null, *, *, *, false) = null 6395 * StringUtils.replace("", *, *, *, false) = "" 6396 * StringUtils.replace("any", null, *, *, false) = "any" 6397 * StringUtils.replace("any", *, null, *, false) = "any" 6398 * StringUtils.replace("any", "", *, *, false) = "any" 6399 * StringUtils.replace("any", *, *, 0, false) = "any" 6400 * StringUtils.replace("abaa", "a", null, -1, false) = "abaa" 6401 * StringUtils.replace("abaa", "a", "", -1, false) = "b" 6402 * StringUtils.replace("abaa", "a", "z", 0, false) = "abaa" 6403 * StringUtils.replace("abaa", "A", "z", 1, false) = "abaa" 6404 * StringUtils.replace("abaa", "A", "z", 1, true) = "zbaa" 6405 * StringUtils.replace("abAa", "a", "z", 2, true) = "zbza" 6406 * StringUtils.replace("abAa", "a", "z", -1, true) = "zbzz" 6407 * </pre> 6408 * 6409 * @param text text to search and replace in, may be null 6410 * @param searchString the String to search for (case insensitive), may be null 6411 * @param replacement the String to replace it with, may be null 6412 * @param max maximum number of values to replace, or {@code -1} if no maximum 6413 * @param ignoreCase if true replace is case insensitive, otherwise case sensitive 6414 * @return the text with any replacements processed, 6415 * {@code null} if null String input 6416 */ 6417 private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) { 6418 if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { 6419 return text; 6420 } 6421 if (ignoreCase) { 6422 searchString = searchString.toLowerCase(); 6423 } 6424 int start = 0; 6425 int end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start); 6426 if (end == INDEX_NOT_FOUND) { 6427 return text; 6428 } 6429 final int replLength = searchString.length(); 6430 int increase = replacement.length() - replLength; 6431 increase = increase < 0 ? 0 : increase; 6432 increase *= max < 0 ? 16 : max > 64 ? 64 : max; 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 (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) { 6695 return text; 6696 } 6697 6698 // if recursing, this shouldn't be less than 0 6699 if (timeToLive < 0) { 6700 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6701 "output of one loop is the input of another"); 6702 } 6703 6704 final int searchLength = searchList.length; 6705 final int replacementLength = replacementList.length; 6706 6707 // make sure lengths are ok, these need to be equal 6708 if (searchLength != replacementLength) { 6709 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6710 + searchLength 6711 + " vs " 6712 + replacementLength); 6713 } 6714 6715 // keep track of which still have matches 6716 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6717 6718 // index on index that the match was found 6719 int textIndex = -1; 6720 int replaceIndex = -1; 6721 int tempIndex = -1; 6722 6723 // index of replace array that will replace the search string found 6724 // NOTE: logic duplicated below START 6725 for (int i = 0; i < searchLength; i++) { 6726 if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 6727 searchList[i].isEmpty() || replacementList[i] == null) { 6728 continue; 6729 } 6730 tempIndex = text.indexOf(searchList[i]); 6731 6732 // see if we need to keep searching for this 6733 if (tempIndex == -1) { 6734 noMoreMatchesForReplIndex[i] = true; 6735 } else { 6736 if (textIndex == -1 || tempIndex < textIndex) { 6737 textIndex = tempIndex; 6738 replaceIndex = i; 6739 } 6740 } 6741 } 6742 // NOTE: logic mostly below END 6743 6744 // no search strings found, we are done 6745 if (textIndex == -1) { 6746 return text; 6747 } 6748 6749 int start = 0; 6750 6751 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6752 int increase = 0; 6753 6754 // count the replacement text elements that are larger than their corresponding text being replaced 6755 for (int i = 0; i < searchList.length; i++) { 6756 if (searchList[i] == null || replacementList[i] == null) { 6757 continue; 6758 } 6759 final int greater = replacementList[i].length() - searchList[i].length(); 6760 if (greater > 0) { 6761 increase += 3 * greater; // assume 3 matches 6762 } 6763 } 6764 // have upper-bound at 20% increase, then let Java take over 6765 increase = Math.min(increase, text.length() / 5); 6766 6767 final StringBuilder buf = new StringBuilder(text.length() + increase); 6768 6769 while (textIndex != -1) { 6770 6771 for (int i = start; i < textIndex; i++) { 6772 buf.append(text.charAt(i)); 6773 } 6774 buf.append(replacementList[replaceIndex]); 6775 6776 start = textIndex + searchList[replaceIndex].length(); 6777 6778 textIndex = -1; 6779 replaceIndex = -1; 6780 tempIndex = -1; 6781 // find the next earliest match 6782 // NOTE: logic mostly duplicated above START 6783 for (int i = 0; i < searchLength; i++) { 6784 if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 6785 searchList[i].isEmpty() || replacementList[i] == null) { 6786 continue; 6787 } 6788 tempIndex = text.indexOf(searchList[i], start); 6789 6790 // see if we need to keep searching for this 6791 if (tempIndex == -1) { 6792 noMoreMatchesForReplIndex[i] = true; 6793 } else { 6794 if (textIndex == -1 || tempIndex < textIndex) { 6795 textIndex = tempIndex; 6796 replaceIndex = i; 6797 } 6798 } 6799 } 6800 // NOTE: logic duplicated above END 6801 6802 } 6803 final int textLength = text.length(); 6804 for (int i = start; i < textLength; i++) { 6805 buf.append(text.charAt(i)); 6806 } 6807 final String result = buf.toString(); 6808 if (!repeat) { 6809 return result; 6810 } 6811 6812 return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); 6813 } 6814 6815 /** 6816 * <p> 6817 * Replaces all occurrences of Strings within another String. 6818 * </p> 6819 * 6820 * <p> 6821 * A {@code null} reference passed to this method is a no-op, or if 6822 * any "search string" or "string to replace" is null, that replace will be 6823 * ignored. 6824 * </p> 6825 * 6826 * <pre> 6827 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6828 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6829 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6830 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6831 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6832 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6833 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6834 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6835 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6836 * (example of how it repeats) 6837 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6838 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException 6839 * </pre> 6840 * 6841 * @param text 6842 * text to search and replace in, no-op if null 6843 * @param searchList 6844 * the Strings to search for, no-op if null 6845 * @param replacementList 6846 * the Strings to replace them with, no-op if null 6847 * @return the text with any replacements processed, {@code null} if 6848 * null String input 6849 * @throws IllegalStateException 6850 * if the search is repeating and there is an endless loop due 6851 * to outputs of one being inputs to another 6852 * @throws IllegalArgumentException 6853 * if the lengths of the arrays are not the same (null is ok, 6854 * and/or size 0) 6855 * @since 2.4 6856 */ 6857 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6858 // timeToLive should be 0 if not used or nothing to replace, else it's 6859 // the length of the replace array 6860 final int timeToLive = searchList == null ? 0 : searchList.length; 6861 return replaceEach(text, searchList, replacementList, true, timeToLive); 6862 } 6863 6864 /** 6865 * <p>Replaces the first substring of the text string that matches the given regular expression 6866 * with the given replacement.</p> 6867 * 6868 * This method is a {@code null} safe equivalent to: 6869 * <ul> 6870 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6871 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6872 * </ul> 6873 * 6874 * <p>A {@code null} reference passed to this method is a no-op.</p> 6875 * 6876 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 6877 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6878 * DOTALL is also known as single-line mode in Perl.</p> 6879 * 6880 * <pre> 6881 * StringUtils.replaceFirst(null, *, *) = null 6882 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6883 * StringUtils.replaceFirst("any", *, null) = "any" 6884 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6885 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6886 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6887 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6888 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6889 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6890 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6891 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6892 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6893 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6894 * </pre> 6895 * 6896 * @param text text to search and replace in, may be null 6897 * @param regex the regular expression to which this string is to be matched 6898 * @param replacement the string to be substituted for the first match 6899 * @return the text with the first replacement processed, 6900 * {@code null} if null String input 6901 * 6902 * @throws java.util.regex.PatternSyntaxException 6903 * if the regular expression's syntax is invalid 6904 * 6905 * @see String#replaceFirst(String, String) 6906 * @see java.util.regex.Pattern 6907 * @see java.util.regex.Pattern#DOTALL 6908 * @since 3.5 6909 * 6910 * @deprecated Moved to RegExUtils. 6911 */ 6912 @Deprecated 6913 public static String replaceFirst(final String text, final String regex, final String replacement) { 6914 return RegExUtils.replaceFirst(text, regex, replacement); 6915 } 6916 6917 /** 6918 * <p>Case insensitively replaces all occurrences of a String within another String.</p> 6919 * 6920 * <p>A {@code null} reference passed to this method is a no-op.</p> 6921 * 6922 * <pre> 6923 * StringUtils.replaceIgnoreCase(null, *, *) = null 6924 * StringUtils.replaceIgnoreCase("", *, *) = "" 6925 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6926 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6927 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6928 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6929 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6930 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6931 * </pre> 6932 * 6933 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6934 * @param text text to search and replace in, may be null 6935 * @param searchString the String to search for (case insensitive), may be null 6936 * @param replacement the String to replace it with, may be null 6937 * @return the text with any replacements processed, 6938 * {@code null} if null String input 6939 * @since 3.5 6940 */ 6941 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6942 return replaceIgnoreCase(text, searchString, replacement, -1); 6943 } 6944 6945 /** 6946 * <p>Case insensitively replaces a String with another String inside a larger String, 6947 * for the first {@code max} values of the search String.</p> 6948 * 6949 * <p>A {@code null} reference passed to this method is a no-op.</p> 6950 * 6951 * <pre> 6952 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6953 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6954 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6955 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6956 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6957 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6958 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6959 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6960 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6961 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6962 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6963 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6964 * </pre> 6965 * 6966 * @param text text to search and replace in, may be null 6967 * @param searchString the String to search for (case insensitive), may be null 6968 * @param replacement the String to replace it with, may be null 6969 * @param max maximum number of values to replace, or {@code -1} if no maximum 6970 * @return the text with any replacements processed, 6971 * {@code null} if null String input 6972 * @since 3.5 6973 */ 6974 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6975 return replace(text, searchString, replacement, max, true); 6976 } 6977 6978 // Replacing 6979 //----------------------------------------------------------------------- 6980 /** 6981 * <p>Replaces a String with another String inside a larger String, once.</p> 6982 * 6983 * <p>A {@code null} reference passed to this method is a no-op.</p> 6984 * 6985 * <pre> 6986 * StringUtils.replaceOnce(null, *, *) = null 6987 * StringUtils.replaceOnce("", *, *) = "" 6988 * StringUtils.replaceOnce("any", null, *) = "any" 6989 * StringUtils.replaceOnce("any", *, null) = "any" 6990 * StringUtils.replaceOnce("any", "", *) = "any" 6991 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6992 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6993 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6994 * </pre> 6995 * 6996 * @see #replace(String text, String searchString, String replacement, int max) 6997 * @param text text to search and replace in, may be null 6998 * @param searchString the String to search for, may be null 6999 * @param replacement the String to replace with, may be null 7000 * @return the text with any replacements processed, 7001 * {@code null} if null String input 7002 */ 7003 public static String replaceOnce(final String text, final String searchString, final String replacement) { 7004 return replace(text, searchString, replacement, 1); 7005 } 7006 7007 /** 7008 * <p>Case insensitively replaces a String with another String inside a larger String, once.</p> 7009 * 7010 * <p>A {@code null} reference passed to this method is a no-op.</p> 7011 * 7012 * <pre> 7013 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 7014 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 7015 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 7016 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 7017 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 7018 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 7019 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 7020 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 7021 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 7022 * </pre> 7023 * 7024 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 7025 * @param text text to search and replace in, may be null 7026 * @param searchString the String to search for (case insensitive), may be null 7027 * @param replacement the String to replace with, may be null 7028 * @return the text with any replacements processed, 7029 * {@code null} if null String input 7030 * @since 3.5 7031 */ 7032 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 7033 return replaceIgnoreCase(text, searchString, replacement, 1); 7034 } 7035 7036 /** 7037 * <p>Replaces each substring of the source String that matches the given regular expression with the given 7038 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.</p> 7039 * 7040 * This call is a {@code null} safe equivalent to: 7041 * <ul> 7042 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 7043 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 7044 * </ul> 7045 * 7046 * <p>A {@code null} reference passed to this method is a no-op.</p> 7047 * 7048 * <pre> 7049 * StringUtils.replacePattern(null, *, *) = null 7050 * StringUtils.replacePattern("any", (String) null, *) = "any" 7051 * StringUtils.replacePattern("any", *, null) = "any" 7052 * StringUtils.replacePattern("", "", "zzz") = "zzz" 7053 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 7054 * StringUtils.replacePattern("", ".+", "zzz") = "" 7055 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 7056 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 7057 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 7058 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 7059 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 7060 * </pre> 7061 * 7062 * @param source 7063 * the source string 7064 * @param regex 7065 * the regular expression to which this string is to be matched 7066 * @param replacement 7067 * the string to be substituted for each match 7068 * @return The resulting {@code String} 7069 * @see #replaceAll(String, String, String) 7070 * @see String#replaceAll(String, String) 7071 * @see Pattern#DOTALL 7072 * @since 3.2 7073 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 7074 * 7075 * @deprecated Moved to RegExUtils. 7076 */ 7077 @Deprecated 7078 public static String replacePattern(final String source, final String regex, final String replacement) { 7079 return RegExUtils.replacePattern(source, regex, replacement); 7080 } 7081 7082 // Reversing 7083 //----------------------------------------------------------------------- 7084 /** 7085 * <p>Reverses a String as per {@link StringBuilder#reverse()}.</p> 7086 * 7087 * <p>A {@code null} String returns {@code null}.</p> 7088 * 7089 * <pre> 7090 * StringUtils.reverse(null) = null 7091 * StringUtils.reverse("") = "" 7092 * StringUtils.reverse("bat") = "tab" 7093 * </pre> 7094 * 7095 * @param str the String to reverse, may be null 7096 * @return the reversed String, {@code null} if null String input 7097 */ 7098 public static String reverse(final String str) { 7099 if (str == null) { 7100 return null; 7101 } 7102 return new StringBuilder(str).reverse().toString(); 7103 } 7104 7105 /** 7106 * <p>Reverses a String that is delimited by a specific character.</p> 7107 * 7108 * <p>The Strings between the delimiters are not reversed. 7109 * Thus java.lang.String becomes String.lang.java (if the delimiter 7110 * is {@code '.'}).</p> 7111 * 7112 * <pre> 7113 * StringUtils.reverseDelimited(null, *) = null 7114 * StringUtils.reverseDelimited("", *) = "" 7115 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 7116 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 7117 * </pre> 7118 * 7119 * @param str the String to reverse, may be null 7120 * @param separatorChar the separator character to use 7121 * @return the reversed String, {@code null} if null String input 7122 * @since 2.0 7123 */ 7124 public static String reverseDelimited(final String str, final char separatorChar) { 7125 if (str == null) { 7126 return null; 7127 } 7128 // could implement manually, but simple way is to reuse other, 7129 // probably slower, methods. 7130 final String[] strs = split(str, separatorChar); 7131 ArrayUtils.reverse(strs); 7132 return join(strs, separatorChar); 7133 } 7134 7135 /** 7136 * <p>Gets the rightmost {@code len} characters of a String.</p> 7137 * 7138 * <p>If {@code len} characters are not available, or the String 7139 * is {@code null}, the String will be returned without an 7140 * an exception. An empty String is returned if len is negative.</p> 7141 * 7142 * <pre> 7143 * StringUtils.right(null, *) = null 7144 * StringUtils.right(*, -ve) = "" 7145 * StringUtils.right("", *) = "" 7146 * StringUtils.right("abc", 0) = "" 7147 * StringUtils.right("abc", 2) = "bc" 7148 * StringUtils.right("abc", 4) = "abc" 7149 * </pre> 7150 * 7151 * @param str the String to get the rightmost characters from, may be null 7152 * @param len the length of the required String 7153 * @return the rightmost characters, {@code null} if null String input 7154 */ 7155 public static String right(final String str, final int len) { 7156 if (str == null) { 7157 return null; 7158 } 7159 if (len < 0) { 7160 return EMPTY; 7161 } 7162 if (str.length() <= len) { 7163 return str; 7164 } 7165 return str.substring(str.length() - len); 7166 } 7167 7168 /** 7169 * <p>Right pad a String with spaces (' ').</p> 7170 * 7171 * <p>The String is padded to the size of {@code size}.</p> 7172 * 7173 * <pre> 7174 * StringUtils.rightPad(null, *) = null 7175 * StringUtils.rightPad("", 3) = " " 7176 * StringUtils.rightPad("bat", 3) = "bat" 7177 * StringUtils.rightPad("bat", 5) = "bat " 7178 * StringUtils.rightPad("bat", 1) = "bat" 7179 * StringUtils.rightPad("bat", -1) = "bat" 7180 * </pre> 7181 * 7182 * @param str the String to pad out, may be null 7183 * @param size the size to pad to 7184 * @return right padded String or original String if no padding is necessary, 7185 * {@code null} if null String input 7186 */ 7187 public static String rightPad(final String str, final int size) { 7188 return rightPad(str, size, ' '); 7189 } 7190 7191 /** 7192 * <p>Right pad a String with a specified character.</p> 7193 * 7194 * <p>The String is padded to the size of {@code size}.</p> 7195 * 7196 * <pre> 7197 * StringUtils.rightPad(null, *, *) = null 7198 * StringUtils.rightPad("", 3, 'z') = "zzz" 7199 * StringUtils.rightPad("bat", 3, 'z') = "bat" 7200 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 7201 * StringUtils.rightPad("bat", 1, 'z') = "bat" 7202 * StringUtils.rightPad("bat", -1, 'z') = "bat" 7203 * </pre> 7204 * 7205 * @param str the String to pad out, may be null 7206 * @param size the size to pad to 7207 * @param padChar the character to pad with 7208 * @return right padded String or original String if no padding is necessary, 7209 * {@code null} if null String input 7210 * @since 2.0 7211 */ 7212 public static String rightPad(final String str, final int size, final char padChar) { 7213 if (str == null) { 7214 return null; 7215 } 7216 final int pads = size - str.length(); 7217 if (pads <= 0) { 7218 return str; // returns original String when possible 7219 } 7220 if (pads > PAD_LIMIT) { 7221 return rightPad(str, size, String.valueOf(padChar)); 7222 } 7223 return str.concat(repeat(padChar, pads)); 7224 } 7225 7226 /** 7227 * <p>Right pad a String with a specified String.</p> 7228 * 7229 * <p>The String is padded to the size of {@code size}.</p> 7230 * 7231 * <pre> 7232 * StringUtils.rightPad(null, *, *) = null 7233 * StringUtils.rightPad("", 3, "z") = "zzz" 7234 * StringUtils.rightPad("bat", 3, "yz") = "bat" 7235 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 7236 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 7237 * StringUtils.rightPad("bat", 1, "yz") = "bat" 7238 * StringUtils.rightPad("bat", -1, "yz") = "bat" 7239 * StringUtils.rightPad("bat", 5, null) = "bat " 7240 * StringUtils.rightPad("bat", 5, "") = "bat " 7241 * </pre> 7242 * 7243 * @param str the String to pad out, may be null 7244 * @param size the size to pad to 7245 * @param padStr the String to pad with, null or empty treated as single space 7246 * @return right padded String or original String if no padding is necessary, 7247 * {@code null} if null String input 7248 */ 7249 public static String rightPad(final String str, final int size, String padStr) { 7250 if (str == null) { 7251 return null; 7252 } 7253 if (isEmpty(padStr)) { 7254 padStr = SPACE; 7255 } 7256 final int padLen = padStr.length(); 7257 final int strLen = str.length(); 7258 final int pads = size - strLen; 7259 if (pads <= 0) { 7260 return str; // returns original String when possible 7261 } 7262 if (padLen == 1 && pads <= PAD_LIMIT) { 7263 return rightPad(str, size, padStr.charAt(0)); 7264 } 7265 7266 if (pads == padLen) { 7267 return str.concat(padStr); 7268 } else if (pads < padLen) { 7269 return str.concat(padStr.substring(0, pads)); 7270 } else { 7271 final char[] padding = new char[pads]; 7272 final char[] padChars = padStr.toCharArray(); 7273 for (int i = 0; i < pads; i++) { 7274 padding[i] = padChars[i % padLen]; 7275 } 7276 return str.concat(new String(padding)); 7277 } 7278 } 7279 7280 // Rotating (circular shift) 7281 //----------------------------------------------------------------------- 7282 /** 7283 * <p>Rotate (circular shift) a String of {@code shift} characters.</p> 7284 * <ul> 7285 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 7286 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 7287 * </ul> 7288 * 7289 * <pre> 7290 * StringUtils.rotate(null, *) = null 7291 * StringUtils.rotate("", *) = "" 7292 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 7293 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 7294 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 7295 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 7296 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 7297 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 7298 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 7299 * </pre> 7300 * 7301 * @param str the String to rotate, may be null 7302 * @param shift number of time to shift (positive : right shift, negative : left shift) 7303 * @return the rotated String, 7304 * or the original String if {@code shift == 0}, 7305 * or {@code null} if null String input 7306 * @since 3.5 7307 */ 7308 public static String rotate(final String str, final int shift) { 7309 if (str == null) { 7310 return null; 7311 } 7312 7313 final int strLen = str.length(); 7314 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7315 return str; 7316 } 7317 7318 final StringBuilder builder = new StringBuilder(strLen); 7319 final int offset = - (shift % strLen); 7320 builder.append(substring(str, offset)); 7321 builder.append(substring(str, 0, offset)); 7322 return builder.toString(); 7323 } 7324 7325 // Splitting 7326 //----------------------------------------------------------------------- 7327 /** 7328 * <p>Splits the provided text into an array, using whitespace as the 7329 * separator. 7330 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 7331 * 7332 * <p>The separator is not included in the returned String array. 7333 * Adjacent separators are treated as one separator. 7334 * For more control over the split use the StrTokenizer class.</p> 7335 * 7336 * <p>A {@code null} input String returns {@code null}.</p> 7337 * 7338 * <pre> 7339 * StringUtils.split(null) = null 7340 * StringUtils.split("") = [] 7341 * StringUtils.split("abc def") = ["abc", "def"] 7342 * StringUtils.split("abc def") = ["abc", "def"] 7343 * StringUtils.split(" abc ") = ["abc"] 7344 * </pre> 7345 * 7346 * @param str the String to parse, may be null 7347 * @return an array of parsed Strings, {@code null} if null String input 7348 */ 7349 public static String[] split(final String str) { 7350 return split(str, null, -1); 7351 } 7352 7353 /** 7354 * <p>Splits the provided text into an array, separator specified. 7355 * This is an alternative to using StringTokenizer.</p> 7356 * 7357 * <p>The separator is not included in the returned String array. 7358 * Adjacent separators are treated as one separator. 7359 * For more control over the split use the StrTokenizer class.</p> 7360 * 7361 * <p>A {@code null} input String returns {@code null}.</p> 7362 * 7363 * <pre> 7364 * StringUtils.split(null, *) = null 7365 * StringUtils.split("", *) = [] 7366 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7367 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7368 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7369 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7370 * </pre> 7371 * 7372 * @param str the String to parse, may be null 7373 * @param separatorChar the character used as the delimiter 7374 * @return an array of parsed Strings, {@code null} if null String input 7375 * @since 2.0 7376 */ 7377 public static String[] split(final String str, final char separatorChar) { 7378 return splitWorker(str, separatorChar, false); 7379 } 7380 7381 /** 7382 * <p>Splits the provided text into an array, separators specified. 7383 * This is an alternative to using StringTokenizer.</p> 7384 * 7385 * <p>The separator is not included in the returned String array. 7386 * Adjacent separators are treated as one separator. 7387 * For more control over the split use the StrTokenizer class.</p> 7388 * 7389 * <p>A {@code null} input String returns {@code null}. 7390 * A {@code null} separatorChars splits on whitespace.</p> 7391 * 7392 * <pre> 7393 * StringUtils.split(null, *) = null 7394 * StringUtils.split("", *) = [] 7395 * StringUtils.split("abc def", null) = ["abc", "def"] 7396 * StringUtils.split("abc def", " ") = ["abc", "def"] 7397 * StringUtils.split("abc def", " ") = ["abc", "def"] 7398 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7399 * </pre> 7400 * 7401 * @param str the String to parse, may be null 7402 * @param separatorChars the characters used as the delimiters, 7403 * {@code null} splits on whitespace 7404 * @return an array of parsed Strings, {@code null} if null String input 7405 */ 7406 public static String[] split(final String str, final String separatorChars) { 7407 return splitWorker(str, separatorChars, -1, false); 7408 } 7409 7410 /** 7411 * <p>Splits the provided text into an array with a maximum length, 7412 * separators specified.</p> 7413 * 7414 * <p>The separator is not included in the returned String array. 7415 * Adjacent separators are treated as one separator.</p> 7416 * 7417 * <p>A {@code null} input String returns {@code null}. 7418 * A {@code null} separatorChars splits on whitespace.</p> 7419 * 7420 * <p>If more than {@code max} delimited substrings are found, the last 7421 * returned string includes all characters after the first {@code max - 1} 7422 * returned strings (including separator characters).</p> 7423 * 7424 * <pre> 7425 * StringUtils.split(null, *, *) = null 7426 * StringUtils.split("", *, *) = [] 7427 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7428 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7429 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7430 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7431 * </pre> 7432 * 7433 * @param str the String to parse, may be null 7434 * @param separatorChars the characters used as the delimiters, 7435 * {@code null} splits on whitespace 7436 * @param max the maximum number of elements to include in the 7437 * array. A zero or negative value implies no limit 7438 * @return an array of parsed Strings, {@code null} if null String input 7439 */ 7440 public static String[] split(final String str, final String separatorChars, final int max) { 7441 return splitWorker(str, separatorChars, max, false); 7442 } 7443 7444 /** 7445 * <p>Splits a String by Character type as returned by 7446 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7447 * characters of the same type are returned as complete tokens. 7448 * <pre> 7449 * StringUtils.splitByCharacterType(null) = null 7450 * StringUtils.splitByCharacterType("") = [] 7451 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7452 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7453 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7454 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7455 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7456 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 7457 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 7458 * </pre> 7459 * @param str the String to split, may be {@code null} 7460 * @return an array of parsed Strings, {@code null} if null String input 7461 * @since 2.4 7462 */ 7463 public static String[] splitByCharacterType(final String str) { 7464 return splitByCharacterType(str, false); 7465 } 7466 7467 /** 7468 * <p>Splits a String by Character type as returned by 7469 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7470 * characters of the same type are returned as complete tokens, with the 7471 * following exception: if {@code camelCase} is {@code true}, 7472 * the character of type {@code Character.UPPERCASE_LETTER}, if any, 7473 * immediately preceding a token of type {@code Character.LOWERCASE_LETTER} 7474 * will belong to the following token rather than to the preceding, if any, 7475 * {@code Character.UPPERCASE_LETTER} token. 7476 * @param str the String to split, may be {@code null} 7477 * @param camelCase whether to use so-called "camel-case" for letter types 7478 * @return an array of parsed Strings, {@code null} if null String input 7479 * @since 2.4 7480 */ 7481 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 7482 if (str == null) { 7483 return null; 7484 } 7485 if (str.isEmpty()) { 7486 return ArrayUtils.EMPTY_STRING_ARRAY; 7487 } 7488 final char[] c = str.toCharArray(); 7489 final List<String> list = new ArrayList<>(); 7490 int tokenStart = 0; 7491 int currentType = Character.getType(c[tokenStart]); 7492 for (int pos = tokenStart + 1; pos < c.length; pos++) { 7493 final int type = Character.getType(c[pos]); 7494 if (type == currentType) { 7495 continue; 7496 } 7497 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 7498 final int newTokenStart = pos - 1; 7499 if (newTokenStart != tokenStart) { 7500 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 7501 tokenStart = newTokenStart; 7502 } 7503 } else { 7504 list.add(new String(c, tokenStart, pos - tokenStart)); 7505 tokenStart = pos; 7506 } 7507 currentType = type; 7508 } 7509 list.add(new String(c, tokenStart, c.length - tokenStart)); 7510 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7511 } 7512 7513 /** 7514 * <p>Splits a String by Character type as returned by 7515 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7516 * characters of the same type are returned as complete tokens, with the 7517 * following exception: the character of type 7518 * {@code Character.UPPERCASE_LETTER}, if any, immediately 7519 * preceding a token of type {@code Character.LOWERCASE_LETTER} 7520 * will belong to the following token rather than to the preceding, if any, 7521 * {@code Character.UPPERCASE_LETTER} token. 7522 * <pre> 7523 * StringUtils.splitByCharacterTypeCamelCase(null) = null 7524 * StringUtils.splitByCharacterTypeCamelCase("") = [] 7525 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7526 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7527 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7528 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 7529 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 7530 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 7531 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 7532 * </pre> 7533 * @param str the String to split, may be {@code null} 7534 * @return an array of parsed Strings, {@code null} if null String input 7535 * @since 2.4 7536 */ 7537 public static String[] splitByCharacterTypeCamelCase(final String str) { 7538 return splitByCharacterType(str, true); 7539 } 7540 7541 /** 7542 * <p>Splits the provided text into an array, separator string specified.</p> 7543 * 7544 * <p>The separator(s) will not be included in the returned String array. 7545 * Adjacent separators are treated as one separator.</p> 7546 * 7547 * <p>A {@code null} input String returns {@code null}. 7548 * A {@code null} separator splits on whitespace.</p> 7549 * 7550 * <pre> 7551 * StringUtils.splitByWholeSeparator(null, *) = null 7552 * StringUtils.splitByWholeSeparator("", *) = [] 7553 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7554 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7555 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7556 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7557 * </pre> 7558 * 7559 * @param str the String to parse, may be null 7560 * @param separator String containing the String to be used as a delimiter, 7561 * {@code null} splits on whitespace 7562 * @return an array of parsed Strings, {@code null} if null String was input 7563 */ 7564 public static String[] splitByWholeSeparator(final String str, final String separator) { 7565 return splitByWholeSeparatorWorker(str, separator, -1, false); 7566 } 7567 7568 /** 7569 * <p>Splits the provided text into an array, separator string specified. 7570 * Returns a maximum of {@code max} substrings.</p> 7571 * 7572 * <p>The separator(s) will not be included in the returned String array. 7573 * Adjacent separators are treated as one separator.</p> 7574 * 7575 * <p>A {@code null} input String returns {@code null}. 7576 * A {@code null} separator splits on whitespace.</p> 7577 * 7578 * <pre> 7579 * StringUtils.splitByWholeSeparator(null, *, *) = null 7580 * StringUtils.splitByWholeSeparator("", *, *) = [] 7581 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7582 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7583 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7584 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7585 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7586 * </pre> 7587 * 7588 * @param str the String to parse, may be null 7589 * @param separator String containing the String to be used as a delimiter, 7590 * {@code null} splits on whitespace 7591 * @param max the maximum number of elements to include in the returned 7592 * array. A zero or negative value implies no limit. 7593 * @return an array of parsed Strings, {@code null} if null String was input 7594 */ 7595 public static String[] splitByWholeSeparator( final String str, final String separator, final int max) { 7596 return splitByWholeSeparatorWorker(str, separator, max, false); 7597 } 7598 7599 /** 7600 * <p>Splits the provided text into an array, separator string specified. </p> 7601 * 7602 * <p>The separator is not included in the returned String array. 7603 * Adjacent separators are treated as separators for empty tokens. 7604 * For more control over the split use the StrTokenizer class.</p> 7605 * 7606 * <p>A {@code null} input String returns {@code null}. 7607 * A {@code null} separator splits on whitespace.</p> 7608 * 7609 * <pre> 7610 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 7611 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 7612 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 7613 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 7614 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7615 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7616 * </pre> 7617 * 7618 * @param str the String to parse, may be null 7619 * @param separator String containing the String to be used as a delimiter, 7620 * {@code null} splits on whitespace 7621 * @return an array of parsed Strings, {@code null} if null String was input 7622 * @since 2.4 7623 */ 7624 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 7625 return splitByWholeSeparatorWorker(str, separator, -1, true); 7626 } 7627 7628 /** 7629 * <p>Splits the provided text into an array, separator string specified. 7630 * Returns a maximum of {@code max} substrings.</p> 7631 * 7632 * <p>The separator is not included in the returned String array. 7633 * Adjacent separators are treated as separators for empty tokens. 7634 * For more control over the split use the StrTokenizer class.</p> 7635 * 7636 * <p>A {@code null} input String returns {@code null}. 7637 * A {@code null} separator splits on whitespace.</p> 7638 * 7639 * <pre> 7640 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 7641 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 7642 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7643 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7644 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7645 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7646 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7647 * </pre> 7648 * 7649 * @param str the String to parse, may be null 7650 * @param separator String containing the String to be used as a delimiter, 7651 * {@code null} splits on whitespace 7652 * @param max the maximum number of elements to include in the returned 7653 * array. A zero or negative value implies no limit. 7654 * @return an array of parsed Strings, {@code null} if null String was input 7655 * @since 2.4 7656 */ 7657 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 7658 return splitByWholeSeparatorWorker(str, separator, max, true); 7659 } 7660 7661 /** 7662 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 7663 * 7664 * @param str the String to parse, may be {@code null} 7665 * @param separator String containing the String to be used as a delimiter, 7666 * {@code null} splits on whitespace 7667 * @param max the maximum number of elements to include in the returned 7668 * array. A zero or negative value implies no limit. 7669 * @param preserveAllTokens if {@code true}, adjacent separators are 7670 * treated as empty token separators; if {@code false}, adjacent 7671 * separators are treated as one separator. 7672 * @return an array of parsed Strings, {@code null} if null String input 7673 * @since 2.4 7674 */ 7675 private static String[] splitByWholeSeparatorWorker( 7676 final String str, final String separator, final int max, final boolean preserveAllTokens) { 7677 if (str == null) { 7678 return null; 7679 } 7680 7681 final int len = str.length(); 7682 7683 if (len == 0) { 7684 return ArrayUtils.EMPTY_STRING_ARRAY; 7685 } 7686 7687 if (separator == null || EMPTY.equals(separator)) { 7688 // Split on whitespace. 7689 return splitWorker(str, null, max, preserveAllTokens); 7690 } 7691 7692 final int separatorLength = separator.length(); 7693 7694 final ArrayList<String> substrings = new ArrayList<>(); 7695 int numberOfSubstrings = 0; 7696 int beg = 0; 7697 int end = 0; 7698 while (end < len) { 7699 end = str.indexOf(separator, beg); 7700 7701 if (end > -1) { 7702 if (end > beg) { 7703 numberOfSubstrings += 1; 7704 7705 if (numberOfSubstrings == max) { 7706 end = len; 7707 substrings.add(str.substring(beg)); 7708 } else { 7709 // The following is OK, because String.substring( beg, end ) excludes 7710 // the character at the position 'end'. 7711 substrings.add(str.substring(beg, end)); 7712 7713 // Set the starting point for the next search. 7714 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 7715 // which is the right calculation: 7716 beg = end + separatorLength; 7717 } 7718 } else { 7719 // We found a consecutive occurrence of the separator, so skip it. 7720 if (preserveAllTokens) { 7721 numberOfSubstrings += 1; 7722 if (numberOfSubstrings == max) { 7723 end = len; 7724 substrings.add(str.substring(beg)); 7725 } else { 7726 substrings.add(EMPTY); 7727 } 7728 } 7729 beg = end + separatorLength; 7730 } 7731 } else { 7732 // String.substring( beg ) goes from 'beg' to the end of the String. 7733 substrings.add(str.substring(beg)); 7734 end = len; 7735 } 7736 } 7737 7738 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7739 } 7740 7741 // ----------------------------------------------------------------------- 7742 /** 7743 * <p>Splits the provided text into an array, using whitespace as the 7744 * separator, preserving all tokens, including empty tokens created by 7745 * adjacent separators. This is an alternative to using StringTokenizer. 7746 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 7747 * 7748 * <p>The separator is not included in the returned String array. 7749 * Adjacent separators are treated as separators for empty tokens. 7750 * For more control over the split use the StrTokenizer class.</p> 7751 * 7752 * <p>A {@code null} input String returns {@code null}.</p> 7753 * 7754 * <pre> 7755 * StringUtils.splitPreserveAllTokens(null) = null 7756 * StringUtils.splitPreserveAllTokens("") = [] 7757 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 7758 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 7759 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 7760 * </pre> 7761 * 7762 * @param str the String to parse, may be {@code null} 7763 * @return an array of parsed Strings, {@code null} if null String input 7764 * @since 2.1 7765 */ 7766 public static String[] splitPreserveAllTokens(final String str) { 7767 return splitWorker(str, null, -1, true); 7768 } 7769 7770 /** 7771 * <p>Splits the provided text into an array, separator specified, 7772 * preserving all tokens, including empty tokens created by adjacent 7773 * separators. This is an alternative to using StringTokenizer.</p> 7774 * 7775 * <p>The separator is not included in the returned String array. 7776 * Adjacent separators are treated as separators for empty tokens. 7777 * For more control over the split use the StrTokenizer class.</p> 7778 * 7779 * <p>A {@code null} input String returns {@code null}.</p> 7780 * 7781 * <pre> 7782 * StringUtils.splitPreserveAllTokens(null, *) = null 7783 * StringUtils.splitPreserveAllTokens("", *) = [] 7784 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 7785 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 7786 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 7787 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 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 b c", ' ') = ["", a", "b", "c"] 7792 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"] 7793 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""] 7794 * </pre> 7795 * 7796 * @param str the String to parse, may be {@code null} 7797 * @param separatorChar the character used as the delimiter, 7798 * {@code null} splits on whitespace 7799 * @return an array of parsed Strings, {@code null} if null String input 7800 * @since 2.1 7801 */ 7802 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 7803 return splitWorker(str, separatorChar, true); 7804 } 7805 7806 /** 7807 * <p>Splits the provided text into an array, separators specified, 7808 * preserving all tokens, including empty tokens created by adjacent 7809 * separators. This is an alternative to using StringTokenizer.</p> 7810 * 7811 * <p>The separator is not included in the returned String array. 7812 * Adjacent separators are treated as separators for empty tokens. 7813 * For more control over the split use the StrTokenizer class.</p> 7814 * 7815 * <p>A {@code null} input String returns {@code null}. 7816 * A {@code null} separatorChars splits on whitespace.</p> 7817 * 7818 * <pre> 7819 * StringUtils.splitPreserveAllTokens(null, *) = null 7820 * StringUtils.splitPreserveAllTokens("", *) = [] 7821 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 7822 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 7823 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"] 7824 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7825 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 7826 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 7827 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"] 7828 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"] 7829 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"] 7830 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""] 7831 * </pre> 7832 * 7833 * @param str the String to parse, may be {@code null} 7834 * @param separatorChars the characters used as the delimiters, 7835 * {@code null} splits on whitespace 7836 * @return an array of parsed Strings, {@code null} if null String input 7837 * @since 2.1 7838 */ 7839 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 7840 return splitWorker(str, separatorChars, -1, true); 7841 } 7842 7843 /** 7844 * <p>Splits the provided text into an array with a maximum length, 7845 * separators specified, preserving all tokens, including empty tokens 7846 * created by adjacent separators.</p> 7847 * 7848 * <p>The separator is not included in the returned String array. 7849 * Adjacent separators are treated as separators for empty tokens. 7850 * Adjacent separators are treated as one separator.</p> 7851 * 7852 * <p>A {@code null} input String returns {@code null}. 7853 * A {@code null} separatorChars splits on whitespace.</p> 7854 * 7855 * <p>If more than {@code max} delimited substrings are found, the last 7856 * returned string includes all characters after the first {@code max - 1} 7857 * returned strings (including separator characters).</p> 7858 * 7859 * <pre> 7860 * StringUtils.splitPreserveAllTokens(null, *, *) = null 7861 * StringUtils.splitPreserveAllTokens("", *, *) = [] 7862 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7863 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7864 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7865 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7866 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 7867 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 7868 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 7869 * </pre> 7870 * 7871 * @param str the String to parse, may be {@code null} 7872 * @param separatorChars the characters used as the delimiters, 7873 * {@code null} splits on whitespace 7874 * @param max the maximum number of elements to include in the 7875 * array. A zero or negative value implies no limit 7876 * @return an array of parsed Strings, {@code null} if null String input 7877 * @since 2.1 7878 */ 7879 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 7880 return splitWorker(str, separatorChars, max, true); 7881 } 7882 7883 /** 7884 * Performs the logic for the {@code split} and 7885 * {@code splitPreserveAllTokens} methods that do not return a 7886 * maximum array length. 7887 * 7888 * @param str the String to parse, may be {@code null} 7889 * @param separatorChar the separate character 7890 * @param preserveAllTokens if {@code true}, adjacent separators are 7891 * treated as empty token separators; if {@code false}, adjacent 7892 * separators are treated as one separator. 7893 * @return an array of parsed Strings, {@code null} if null String input 7894 */ 7895 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 7896 // Performance tuned for 2.0 (JDK1.4) 7897 7898 if (str == null) { 7899 return null; 7900 } 7901 final int len = str.length(); 7902 if (len == 0) { 7903 return ArrayUtils.EMPTY_STRING_ARRAY; 7904 } 7905 final List<String> list = new ArrayList<>(); 7906 int i = 0, start = 0; 7907 boolean match = false; 7908 boolean lastMatch = false; 7909 while (i < len) { 7910 if (str.charAt(i) == separatorChar) { 7911 if (match || preserveAllTokens) { 7912 list.add(str.substring(start, i)); 7913 match = false; 7914 lastMatch = true; 7915 } 7916 start = ++i; 7917 continue; 7918 } 7919 lastMatch = false; 7920 match = true; 7921 i++; 7922 } 7923 if (match || preserveAllTokens && lastMatch) { 7924 list.add(str.substring(start, i)); 7925 } 7926 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7927 } 7928 7929 /** 7930 * Performs the logic for the {@code split} and 7931 * {@code splitPreserveAllTokens} methods that return a maximum array 7932 * length. 7933 * 7934 * @param str the String to parse, may be {@code null} 7935 * @param separatorChars the separate character 7936 * @param max the maximum number of elements to include in the 7937 * array. A zero or negative value implies no limit. 7938 * @param preserveAllTokens if {@code true}, adjacent separators are 7939 * treated as empty token separators; if {@code false}, adjacent 7940 * separators are treated as one separator. 7941 * @return an array of parsed Strings, {@code null} if null String input 7942 */ 7943 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 7944 // Performance tuned for 2.0 (JDK1.4) 7945 // Direct code is quicker than StringTokenizer. 7946 // Also, StringTokenizer uses isSpace() not isWhitespace() 7947 7948 if (str == null) { 7949 return null; 7950 } 7951 final int len = str.length(); 7952 if (len == 0) { 7953 return ArrayUtils.EMPTY_STRING_ARRAY; 7954 } 7955 final List<String> list = new ArrayList<>(); 7956 int sizePlus1 = 1; 7957 int i = 0, start = 0; 7958 boolean match = false; 7959 boolean lastMatch = false; 7960 if (separatorChars == null) { 7961 // Null separator means use whitespace 7962 while (i < len) { 7963 if (Character.isWhitespace(str.charAt(i))) { 7964 if (match || preserveAllTokens) { 7965 lastMatch = true; 7966 if (sizePlus1++ == max) { 7967 i = len; 7968 lastMatch = false; 7969 } 7970 list.add(str.substring(start, i)); 7971 match = false; 7972 } 7973 start = ++i; 7974 continue; 7975 } 7976 lastMatch = false; 7977 match = true; 7978 i++; 7979 } 7980 } else if (separatorChars.length() == 1) { 7981 // Optimise 1 character case 7982 final char sep = separatorChars.charAt(0); 7983 while (i < len) { 7984 if (str.charAt(i) == sep) { 7985 if (match || preserveAllTokens) { 7986 lastMatch = true; 7987 if (sizePlus1++ == max) { 7988 i = len; 7989 lastMatch = false; 7990 } 7991 list.add(str.substring(start, i)); 7992 match = false; 7993 } 7994 start = ++i; 7995 continue; 7996 } 7997 lastMatch = false; 7998 match = true; 7999 i++; 8000 } 8001 } else { 8002 // standard case 8003 while (i < len) { 8004 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 8005 if (match || preserveAllTokens) { 8006 lastMatch = true; 8007 if (sizePlus1++ == max) { 8008 i = len; 8009 lastMatch = false; 8010 } 8011 list.add(str.substring(start, i)); 8012 match = false; 8013 } 8014 start = ++i; 8015 continue; 8016 } 8017 lastMatch = false; 8018 match = true; 8019 i++; 8020 } 8021 } 8022 if (match || preserveAllTokens && lastMatch) { 8023 list.add(str.substring(start, i)); 8024 } 8025 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8026 } 8027 8028 /** 8029 * <p>Check if a CharSequence starts with a specified prefix.</p> 8030 * 8031 * <p>{@code null}s are handled without exceptions. Two {@code null} 8032 * references are considered to be equal. The comparison is case sensitive.</p> 8033 * 8034 * <pre> 8035 * StringUtils.startsWith(null, null) = true 8036 * StringUtils.startsWith(null, "abc") = false 8037 * StringUtils.startsWith("abcdef", null) = false 8038 * StringUtils.startsWith("abcdef", "abc") = true 8039 * StringUtils.startsWith("ABCDEF", "abc") = false 8040 * </pre> 8041 * 8042 * @see java.lang.String#startsWith(String) 8043 * @param str the CharSequence to check, may be null 8044 * @param prefix the prefix to find, may be null 8045 * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or 8046 * both {@code null} 8047 * @since 2.4 8048 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 8049 */ 8050 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 8051 return startsWith(str, prefix, false); 8052 } 8053 8054 /** 8055 * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p> 8056 * 8057 * @see java.lang.String#startsWith(String) 8058 * @param str the CharSequence to check, may be null 8059 * @param prefix the prefix to find, may be null 8060 * @param ignoreCase indicates whether the compare should ignore case 8061 * (case insensitive) or not. 8062 * @return {@code true} if the CharSequence starts with the prefix or 8063 * both {@code null} 8064 */ 8065 private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) { 8066 if (str == null || prefix == null) { 8067 return str == prefix; 8068 } 8069 if (prefix.length() > str.length()) { 8070 return false; 8071 } 8072 return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length()); 8073 } 8074 8075 /** 8076 * <p>Check if a CharSequence starts with any of the provided case-sensitive prefixes.</p> 8077 * 8078 * <pre> 8079 * StringUtils.startsWithAny(null, null) = false 8080 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 8081 * StringUtils.startsWithAny("abcxyz", null) = false 8082 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true 8083 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 8084 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 8085 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false 8086 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false 8087 * </pre> 8088 * 8089 * @param sequence the CharSequence to check, may be null 8090 * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null} 8091 * @see StringUtils#startsWith(CharSequence, CharSequence) 8092 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or 8093 * the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}. 8094 * @since 2.5 8095 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 8096 */ 8097 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 8098 if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { 8099 return false; 8100 } 8101 for (final CharSequence searchString : searchStrings) { 8102 if (startsWith(sequence, searchString)) { 8103 return true; 8104 } 8105 } 8106 return false; 8107 } 8108 8109 /** 8110 * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p> 8111 * 8112 * <p>{@code null}s are handled without exceptions. Two {@code null} 8113 * references are considered to be equal. The comparison is case insensitive.</p> 8114 * 8115 * <pre> 8116 * StringUtils.startsWithIgnoreCase(null, null) = true 8117 * StringUtils.startsWithIgnoreCase(null, "abc") = false 8118 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 8119 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 8120 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 8121 * </pre> 8122 * 8123 * @see java.lang.String#startsWith(String) 8124 * @param str the CharSequence to check, may be null 8125 * @param prefix the prefix to find, may be null 8126 * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or 8127 * both {@code null} 8128 * @since 2.4 8129 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 8130 */ 8131 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 8132 return startsWith(str, prefix, true); 8133 } 8134 8135 // Stripping 8136 //----------------------------------------------------------------------- 8137 /** 8138 * <p>Strips whitespace from the start and end of a String.</p> 8139 * 8140 * <p>This is similar to {@link #trim(String)} but removes whitespace. 8141 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8142 * 8143 * <p>A {@code null} input String returns {@code null}.</p> 8144 * 8145 * <pre> 8146 * StringUtils.strip(null) = null 8147 * StringUtils.strip("") = "" 8148 * StringUtils.strip(" ") = "" 8149 * StringUtils.strip("abc") = "abc" 8150 * StringUtils.strip(" abc") = "abc" 8151 * StringUtils.strip("abc ") = "abc" 8152 * StringUtils.strip(" abc ") = "abc" 8153 * StringUtils.strip(" ab c ") = "ab c" 8154 * </pre> 8155 * 8156 * @param str the String to remove whitespace from, may be null 8157 * @return the stripped String, {@code null} if null String input 8158 */ 8159 public static String strip(final String str) { 8160 return strip(str, null); 8161 } 8162 8163 /** 8164 * <p>Strips any of a set of characters from the start and end of a String. 8165 * This is similar to {@link String#trim()} but allows the characters 8166 * to be stripped to be controlled.</p> 8167 * 8168 * <p>A {@code null} input String returns {@code null}. 8169 * An empty string ("") input returns the empty string.</p> 8170 * 8171 * <p>If the stripChars String is {@code null}, whitespace is 8172 * stripped as defined by {@link Character#isWhitespace(char)}. 8173 * Alternatively use {@link #strip(String)}.</p> 8174 * 8175 * <pre> 8176 * StringUtils.strip(null, *) = null 8177 * StringUtils.strip("", *) = "" 8178 * StringUtils.strip("abc", null) = "abc" 8179 * StringUtils.strip(" abc", null) = "abc" 8180 * StringUtils.strip("abc ", null) = "abc" 8181 * StringUtils.strip(" abc ", null) = "abc" 8182 * StringUtils.strip(" abcyx", "xyz") = " abc" 8183 * </pre> 8184 * 8185 * @param str the String to remove characters from, may be null 8186 * @param stripChars the characters to remove, null treated as whitespace 8187 * @return the stripped String, {@code null} if null String input 8188 */ 8189 public static String strip(String str, final String stripChars) { 8190 if (isEmpty(str)) { 8191 return str; 8192 } 8193 str = stripStart(str, stripChars); 8194 return stripEnd(str, stripChars); 8195 } 8196 8197 /** 8198 * <p>Removes diacritics (~= accents) from a string. The case will not be altered.</p> 8199 * <p>For instance, 'à' will be replaced by 'a'.</p> 8200 * <p>Note that ligatures will be left as is.</p> 8201 * 8202 * <pre> 8203 * StringUtils.stripAccents(null) = null 8204 * StringUtils.stripAccents("") = "" 8205 * StringUtils.stripAccents("control") = "control" 8206 * StringUtils.stripAccents("éclair") = "eclair" 8207 * </pre> 8208 * 8209 * @param input String to be stripped 8210 * @return input text with diacritics removed 8211 * 8212 * @since 3.0 8213 */ 8214 // 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). 8215 public static String stripAccents(final String input) { 8216 if (input == null) { 8217 return null; 8218 } 8219 final Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$ 8220 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD)); 8221 convertRemainingAccentCharacters(decomposed); 8222 // Note that this doesn't correctly remove ligatures... 8223 return pattern.matcher(decomposed).replaceAll(EMPTY); 8224 } 8225 8226 // StripAll 8227 //----------------------------------------------------------------------- 8228 /** 8229 * <p>Strips whitespace from the start and end of every String in an array. 8230 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8231 * 8232 * <p>A new array is returned each time, except for length zero. 8233 * A {@code null} array will return {@code null}. 8234 * An empty array will return itself. 8235 * A {@code null} array entry will be ignored.</p> 8236 * 8237 * <pre> 8238 * StringUtils.stripAll(null) = null 8239 * StringUtils.stripAll([]) = [] 8240 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 8241 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 8242 * </pre> 8243 * 8244 * @param strs the array to remove whitespace from, may be null 8245 * @return the stripped Strings, {@code null} if null array input 8246 */ 8247 public static String[] stripAll(final String... strs) { 8248 return stripAll(strs, null); 8249 } 8250 8251 /** 8252 * <p>Strips any of a set of characters from the start and end of every 8253 * String in an array.</p> 8254 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8255 * 8256 * <p>A new array is returned each time, except for length zero. 8257 * A {@code null} array will return {@code null}. 8258 * An empty array will return itself. 8259 * A {@code null} array entry will be ignored. 8260 * A {@code null} stripChars will strip whitespace as defined by 8261 * {@link Character#isWhitespace(char)}.</p> 8262 * 8263 * <pre> 8264 * StringUtils.stripAll(null, *) = null 8265 * StringUtils.stripAll([], *) = [] 8266 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 8267 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 8268 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 8269 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 8270 * </pre> 8271 * 8272 * @param strs the array to remove characters from, may be null 8273 * @param stripChars the characters to remove, null treated as whitespace 8274 * @return the stripped Strings, {@code null} if null array input 8275 */ 8276 public static String[] stripAll(final String[] strs, final String stripChars) { 8277 int strsLen; 8278 if (strs == null || (strsLen = strs.length) == 0) { 8279 return strs; 8280 } 8281 final String[] newArr = new String[strsLen]; 8282 for (int i = 0; i < strsLen; i++) { 8283 newArr[i] = strip(strs[i], stripChars); 8284 } 8285 return newArr; 8286 } 8287 8288 /** 8289 * <p>Strips any of a set of characters from the end of a String.</p> 8290 * 8291 * <p>A {@code null} input String returns {@code null}. 8292 * An empty string ("") input returns the empty string.</p> 8293 * 8294 * <p>If the stripChars String is {@code null}, whitespace is 8295 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 8296 * 8297 * <pre> 8298 * StringUtils.stripEnd(null, *) = null 8299 * StringUtils.stripEnd("", *) = "" 8300 * StringUtils.stripEnd("abc", "") = "abc" 8301 * StringUtils.stripEnd("abc", null) = "abc" 8302 * StringUtils.stripEnd(" abc", null) = " abc" 8303 * StringUtils.stripEnd("abc ", null) = "abc" 8304 * StringUtils.stripEnd(" abc ", null) = " abc" 8305 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 8306 * StringUtils.stripEnd("120.00", ".0") = "12" 8307 * </pre> 8308 * 8309 * @param str the String to remove characters from, may be null 8310 * @param stripChars the set of characters to remove, null treated as whitespace 8311 * @return the stripped String, {@code null} if null String input 8312 */ 8313 public static String stripEnd(final String str, final String stripChars) { 8314 int end = length(str); 8315 if (end == 0) { 8316 return str; 8317 } 8318 8319 if (stripChars == null) { 8320 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 8321 end--; 8322 } 8323 } else if (stripChars.isEmpty()) { 8324 return str; 8325 } else { 8326 while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { 8327 end--; 8328 } 8329 } 8330 return str.substring(0, end); 8331 } 8332 8333 /** 8334 * <p>Strips any of a set of characters from the start of a String.</p> 8335 * 8336 * <p>A {@code null} input String returns {@code null}. 8337 * An empty string ("") input returns the empty string.</p> 8338 * 8339 * <p>If the stripChars String is {@code null}, whitespace is 8340 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 8341 * 8342 * <pre> 8343 * StringUtils.stripStart(null, *) = null 8344 * StringUtils.stripStart("", *) = "" 8345 * StringUtils.stripStart("abc", "") = "abc" 8346 * StringUtils.stripStart("abc", null) = "abc" 8347 * StringUtils.stripStart(" abc", null) = "abc" 8348 * StringUtils.stripStart("abc ", null) = "abc " 8349 * StringUtils.stripStart(" abc ", null) = "abc " 8350 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 8351 * </pre> 8352 * 8353 * @param str the String to remove characters from, may be null 8354 * @param stripChars the characters to remove, null treated as whitespace 8355 * @return the stripped String, {@code null} if null String input 8356 */ 8357 public static String stripStart(final String str, final String stripChars) { 8358 final int strLen = length(str); 8359 if (strLen == 0) { 8360 return str; 8361 } 8362 int start = 0; 8363 if (stripChars == null) { 8364 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 8365 start++; 8366 } 8367 } else if (stripChars.isEmpty()) { 8368 return str; 8369 } else { 8370 while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) { 8371 start++; 8372 } 8373 } 8374 return str.substring(start); 8375 } 8376 8377 /** 8378 * <p>Strips whitespace from the start and end of a String returning 8379 * an empty String if {@code null} input.</p> 8380 * 8381 * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace. 8382 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8383 * 8384 * <pre> 8385 * StringUtils.stripToEmpty(null) = "" 8386 * StringUtils.stripToEmpty("") = "" 8387 * StringUtils.stripToEmpty(" ") = "" 8388 * StringUtils.stripToEmpty("abc") = "abc" 8389 * StringUtils.stripToEmpty(" abc") = "abc" 8390 * StringUtils.stripToEmpty("abc ") = "abc" 8391 * StringUtils.stripToEmpty(" abc ") = "abc" 8392 * StringUtils.stripToEmpty(" ab c ") = "ab c" 8393 * </pre> 8394 * 8395 * @param str the String to be stripped, may be null 8396 * @return the trimmed String, or an empty String if {@code null} input 8397 * @since 2.0 8398 */ 8399 public static String stripToEmpty(final String str) { 8400 return str == null ? EMPTY : strip(str, null); 8401 } 8402 8403 /** 8404 * <p>Strips whitespace from the start and end of a String returning 8405 * {@code null} if the String is empty ("") after the strip.</p> 8406 * 8407 * <p>This is similar to {@link #trimToNull(String)} but removes whitespace. 8408 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8409 * 8410 * <pre> 8411 * StringUtils.stripToNull(null) = null 8412 * StringUtils.stripToNull("") = null 8413 * StringUtils.stripToNull(" ") = null 8414 * StringUtils.stripToNull("abc") = "abc" 8415 * StringUtils.stripToNull(" abc") = "abc" 8416 * StringUtils.stripToNull("abc ") = "abc" 8417 * StringUtils.stripToNull(" abc ") = "abc" 8418 * StringUtils.stripToNull(" ab c ") = "ab c" 8419 * </pre> 8420 * 8421 * @param str the String to be stripped, may be null 8422 * @return the stripped String, 8423 * {@code null} if whitespace, empty or null String input 8424 * @since 2.0 8425 */ 8426 public static String stripToNull(String str) { 8427 if (str == null) { 8428 return null; 8429 } 8430 str = strip(str, null); 8431 return str.isEmpty() ? null : str; 8432 } 8433 8434 // Substring 8435 //----------------------------------------------------------------------- 8436 /** 8437 * <p>Gets a substring from the specified String avoiding exceptions.</p> 8438 * 8439 * <p>A negative start position can be used to start {@code n} 8440 * characters from the end of the String.</p> 8441 * 8442 * <p>A {@code null} String will return {@code null}. 8443 * An empty ("") String will return "".</p> 8444 * 8445 * <pre> 8446 * StringUtils.substring(null, *) = null 8447 * StringUtils.substring("", *) = "" 8448 * StringUtils.substring("abc", 0) = "abc" 8449 * StringUtils.substring("abc", 2) = "c" 8450 * StringUtils.substring("abc", 4) = "" 8451 * StringUtils.substring("abc", -2) = "bc" 8452 * StringUtils.substring("abc", -4) = "abc" 8453 * </pre> 8454 * 8455 * @param str the String to get the substring from, may be null 8456 * @param start the position to start from, negative means 8457 * count back from the end of the String by this many characters 8458 * @return substring from start position, {@code null} if null String input 8459 */ 8460 public static String substring(final String str, int start) { 8461 if (str == null) { 8462 return null; 8463 } 8464 8465 // handle negatives, which means last n characters 8466 if (start < 0) { 8467 start = str.length() + start; // remember start is negative 8468 } 8469 8470 if (start < 0) { 8471 start = 0; 8472 } 8473 if (start > str.length()) { 8474 return EMPTY; 8475 } 8476 8477 return str.substring(start); 8478 } 8479 8480 /** 8481 * <p>Gets a substring from the specified String avoiding exceptions.</p> 8482 * 8483 * <p>A negative start position can be used to start/end {@code n} 8484 * characters from the end of the String.</p> 8485 * 8486 * <p>The returned substring starts with the character in the {@code start} 8487 * position and ends before the {@code end} position. All position counting is 8488 * zero-based -- i.e., to start at the beginning of the string use 8489 * {@code start = 0}. Negative start and end positions can be used to 8490 * specify offsets relative to the end of the String.</p> 8491 * 8492 * <p>If {@code start} is not strictly to the left of {@code end}, "" 8493 * is returned.</p> 8494 * 8495 * <pre> 8496 * StringUtils.substring(null, *, *) = null 8497 * StringUtils.substring("", * , *) = ""; 8498 * StringUtils.substring("abc", 0, 2) = "ab" 8499 * StringUtils.substring("abc", 2, 0) = "" 8500 * StringUtils.substring("abc", 2, 4) = "c" 8501 * StringUtils.substring("abc", 4, 6) = "" 8502 * StringUtils.substring("abc", 2, 2) = "" 8503 * StringUtils.substring("abc", -2, -1) = "b" 8504 * StringUtils.substring("abc", -4, 2) = "ab" 8505 * </pre> 8506 * 8507 * @param str the String to get the substring from, may be null 8508 * @param start the position to start from, negative means 8509 * count back from the end of the String by this many characters 8510 * @param end the position to end at (exclusive), negative means 8511 * count back from the end of the String by this many characters 8512 * @return substring from start position to end position, 8513 * {@code null} if null String input 8514 */ 8515 public static String substring(final String str, int start, int end) { 8516 if (str == null) { 8517 return null; 8518 } 8519 8520 // handle negatives 8521 if (end < 0) { 8522 end = str.length() + end; // remember end is negative 8523 } 8524 if (start < 0) { 8525 start = str.length() + start; // remember start is negative 8526 } 8527 8528 // check length next 8529 if (end > str.length()) { 8530 end = str.length(); 8531 } 8532 8533 // if start is greater than end, return "" 8534 if (start > end) { 8535 return EMPTY; 8536 } 8537 8538 if (start < 0) { 8539 start = 0; 8540 } 8541 if (end < 0) { 8542 end = 0; 8543 } 8544 8545 return str.substring(start, end); 8546 } 8547 8548 /** 8549 * <p>Gets the substring after the first occurrence of a separator. 8550 * The separator is not returned.</p> 8551 * 8552 * <p>A {@code null} string input will return {@code null}. 8553 * An empty ("") string input will return the empty string. 8554 * A {@code null} separator will return the empty string if the 8555 * input string is not {@code null}.</p> 8556 * 8557 * <p>If nothing is found, the empty string is returned.</p> 8558 * 8559 * <pre> 8560 * StringUtils.substringAfter(null, *) = null 8561 * StringUtils.substringAfter("", *) = "" 8562 * StringUtils.substringAfter(*, null) = "" 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", "") = "abc" 8568 * </pre> 8569 * 8570 * @param str the String to get a substring from, may be null 8571 * @param separator the String to search for, may be null 8572 * @return the substring after the first occurrence of the separator, 8573 * {@code null} if null String input 8574 * @since 2.0 8575 */ 8576 public static String substringAfter(final String str, final String separator) { 8577 if (isEmpty(str)) { 8578 return str; 8579 } 8580 if (separator == null) { 8581 return EMPTY; 8582 } 8583 final int pos = str.indexOf(separator); 8584 if (pos == INDEX_NOT_FOUND) { 8585 return EMPTY; 8586 } 8587 return str.substring(pos + separator.length()); 8588 } 8589 8590 // startsWith 8591 //----------------------------------------------------------------------- 8592 8593 /** 8594 * <p>Gets the substring after the last occurrence of a separator. 8595 * The separator is not returned.</p> 8596 * 8597 * <p>A {@code null} string input will return {@code null}. 8598 * An empty ("") string input will return the empty string. 8599 * An empty or {@code null} separator will return the empty string if 8600 * the input string is not {@code null}.</p> 8601 * 8602 * <p>If nothing is found, the empty string is returned.</p> 8603 * 8604 * <pre> 8605 * StringUtils.substringAfterLast(null, *) = null 8606 * StringUtils.substringAfterLast("", *) = "" 8607 * StringUtils.substringAfterLast(*, "") = "" 8608 * StringUtils.substringAfterLast(*, null) = "" 8609 * StringUtils.substringAfterLast("abc", "a") = "bc" 8610 * StringUtils.substringAfterLast("abcba", "b") = "a" 8611 * StringUtils.substringAfterLast("abc", "c") = "" 8612 * StringUtils.substringAfterLast("a", "a") = "" 8613 * StringUtils.substringAfterLast("a", "z") = "" 8614 * </pre> 8615 * 8616 * @param str the String to get a substring from, may be null 8617 * @param separator the String to search for, may be null 8618 * @return the substring after the last occurrence of the separator, 8619 * {@code null} if null String input 8620 * @since 2.0 8621 */ 8622 public static String substringAfterLast(final String str, final String separator) { 8623 if (isEmpty(str)) { 8624 return str; 8625 } 8626 if (isEmpty(separator)) { 8627 return EMPTY; 8628 } 8629 final int pos = str.lastIndexOf(separator); 8630 if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) { 8631 return EMPTY; 8632 } 8633 return str.substring(pos + separator.length()); 8634 } 8635 8636 // SubStringAfter/SubStringBefore 8637 //----------------------------------------------------------------------- 8638 /** 8639 * <p>Gets the substring before the first occurrence of a separator. 8640 * The separator is not returned.</p> 8641 * 8642 * <p>A {@code null} string input will return {@code null}. 8643 * An empty ("") string input will return the empty string. 8644 * A {@code null} separator will return the input string.</p> 8645 * 8646 * <p>If nothing is found, the string input is returned.</p> 8647 * 8648 * <pre> 8649 * StringUtils.substringBefore(null, *) = null 8650 * StringUtils.substringBefore("", *) = "" 8651 * StringUtils.substringBefore("abc", "a") = "" 8652 * StringUtils.substringBefore("abcba", "b") = "a" 8653 * StringUtils.substringBefore("abc", "c") = "ab" 8654 * StringUtils.substringBefore("abc", "d") = "abc" 8655 * StringUtils.substringBefore("abc", "") = "" 8656 * StringUtils.substringBefore("abc", null) = "abc" 8657 * </pre> 8658 * 8659 * @param str the String to get a substring from, may be null 8660 * @param separator the String to search for, may be null 8661 * @return the substring before the first occurrence of the separator, 8662 * {@code null} if null String input 8663 * @since 2.0 8664 */ 8665 public static String substringBefore(final String str, final String separator) { 8666 if (isEmpty(str) || separator == null) { 8667 return str; 8668 } 8669 if (separator.isEmpty()) { 8670 return EMPTY; 8671 } 8672 final int pos = str.indexOf(separator); 8673 if (pos == INDEX_NOT_FOUND) { 8674 return str; 8675 } 8676 return str.substring(0, pos); 8677 } 8678 8679 /** 8680 * <p>Gets the substring before the last occurrence of a separator. 8681 * The separator is not returned.</p> 8682 * 8683 * <p>A {@code null} string input will return {@code null}. 8684 * An empty ("") string input will return the empty string. 8685 * An empty or {@code null} separator will return the input string.</p> 8686 * 8687 * <p>If nothing is found, the string input is returned.</p> 8688 * 8689 * <pre> 8690 * StringUtils.substringBeforeLast(null, *) = null 8691 * StringUtils.substringBeforeLast("", *) = "" 8692 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 8693 * StringUtils.substringBeforeLast("abc", "c") = "ab" 8694 * StringUtils.substringBeforeLast("a", "a") = "" 8695 * StringUtils.substringBeforeLast("a", "z") = "a" 8696 * StringUtils.substringBeforeLast("a", null) = "a" 8697 * StringUtils.substringBeforeLast("a", "") = "a" 8698 * </pre> 8699 * 8700 * @param str the String to get a substring from, may be null 8701 * @param separator the String to search for, may be null 8702 * @return the substring before the last occurrence of the separator, 8703 * {@code null} if null String input 8704 * @since 2.0 8705 */ 8706 public static String substringBeforeLast(final String str, final String separator) { 8707 if (isEmpty(str) || isEmpty(separator)) { 8708 return str; 8709 } 8710 final int pos = str.lastIndexOf(separator); 8711 if (pos == INDEX_NOT_FOUND) { 8712 return str; 8713 } 8714 return str.substring(0, pos); 8715 } 8716 8717 // Substring between 8718 //----------------------------------------------------------------------- 8719 /** 8720 * <p>Gets the String that is nested in between two instances of the 8721 * same String.</p> 8722 * 8723 * <p>A {@code null} input String returns {@code null}. 8724 * A {@code null} tag returns {@code null}.</p> 8725 * 8726 * <pre> 8727 * StringUtils.substringBetween(null, *) = null 8728 * StringUtils.substringBetween("", "") = "" 8729 * StringUtils.substringBetween("", "tag") = null 8730 * StringUtils.substringBetween("tagabctag", null) = null 8731 * StringUtils.substringBetween("tagabctag", "") = "" 8732 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 8733 * </pre> 8734 * 8735 * @param str the String containing the substring, may be null 8736 * @param tag the String before and after the substring, may be null 8737 * @return the substring, {@code null} if no match 8738 * @since 2.0 8739 */ 8740 public static String substringBetween(final String str, final String tag) { 8741 return substringBetween(str, tag, tag); 8742 } 8743 8744 // endsWith 8745 //----------------------------------------------------------------------- 8746 8747 /** 8748 * <p>Gets the String that is nested in between two Strings. 8749 * Only the first match is returned.</p> 8750 * 8751 * <p>A {@code null} input String returns {@code null}. 8752 * A {@code null} open/close returns {@code null} (no match). 8753 * An empty ("") open and close returns an empty string.</p> 8754 * 8755 * <pre> 8756 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 8757 * StringUtils.substringBetween(null, *, *) = null 8758 * StringUtils.substringBetween(*, null, *) = null 8759 * StringUtils.substringBetween(*, *, null) = null 8760 * StringUtils.substringBetween("", "", "") = "" 8761 * StringUtils.substringBetween("", "", "]") = null 8762 * StringUtils.substringBetween("", "[", "]") = null 8763 * StringUtils.substringBetween("yabcz", "", "") = "" 8764 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 8765 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 8766 * </pre> 8767 * 8768 * @param str the String containing the substring, may be null 8769 * @param open the String before the substring, may be null 8770 * @param close the String after the substring, may be null 8771 * @return the substring, {@code null} if no match 8772 * @since 2.0 8773 */ 8774 public static String substringBetween(final String str, final String open, final String close) { 8775 if (str == null || open == null || close == null) { 8776 return null; 8777 } 8778 final int start = str.indexOf(open); 8779 if (start != INDEX_NOT_FOUND) { 8780 final int end = str.indexOf(close, start + open.length()); 8781 if (end != INDEX_NOT_FOUND) { 8782 return str.substring(start + open.length(), end); 8783 } 8784 } 8785 return null; 8786 } 8787 8788 /** 8789 * <p>Searches a String for substrings delimited by a start and end tag, 8790 * returning all matching substrings in an array.</p> 8791 * 8792 * <p>A {@code null} input String returns {@code null}. 8793 * A {@code null} open/close returns {@code null} (no match). 8794 * An empty ("") open/close returns {@code null} (no match).</p> 8795 * 8796 * <pre> 8797 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 8798 * StringUtils.substringsBetween(null, *, *) = null 8799 * StringUtils.substringsBetween(*, null, *) = null 8800 * StringUtils.substringsBetween(*, *, null) = null 8801 * StringUtils.substringsBetween("", "[", "]") = [] 8802 * </pre> 8803 * 8804 * @param str the String containing the substrings, null returns null, empty returns empty 8805 * @param open the String identifying the start of the substring, empty returns null 8806 * @param close the String identifying the end of the substring, empty returns null 8807 * @return a String Array of substrings, or {@code null} if no match 8808 * @since 2.3 8809 */ 8810 public static String[] substringsBetween(final String str, final String open, final String close) { 8811 if (str == null || isEmpty(open) || isEmpty(close)) { 8812 return null; 8813 } 8814 final int strLen = str.length(); 8815 if (strLen == 0) { 8816 return ArrayUtils.EMPTY_STRING_ARRAY; 8817 } 8818 final int closeLen = close.length(); 8819 final int openLen = open.length(); 8820 final List<String> list = new ArrayList<>(); 8821 int pos = 0; 8822 while (pos < strLen - closeLen) { 8823 int start = str.indexOf(open, pos); 8824 if (start < 0) { 8825 break; 8826 } 8827 start += openLen; 8828 final int end = str.indexOf(close, start); 8829 if (end < 0) { 8830 break; 8831 } 8832 list.add(str.substring(start, end)); 8833 pos = end + closeLen; 8834 } 8835 if (list.isEmpty()) { 8836 return null; 8837 } 8838 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8839 } 8840 8841 /** 8842 * <p>Swaps the case of a String changing upper and title case to 8843 * lower case, and lower case to upper case.</p> 8844 * 8845 * <ul> 8846 * <li>Upper case character converts to Lower case</li> 8847 * <li>Title case character converts to Lower case</li> 8848 * <li>Lower case character converts to Upper case</li> 8849 * </ul> 8850 * 8851 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#swapCase(String)}. 8852 * A {@code null} input String returns {@code null}.</p> 8853 * 8854 * <pre> 8855 * StringUtils.swapCase(null) = null 8856 * StringUtils.swapCase("") = "" 8857 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 8858 * </pre> 8859 * 8860 * <p>NOTE: This method changed in Lang version 2.0. 8861 * It no longer performs a word based algorithm. 8862 * If you only use ASCII, you will notice no change. 8863 * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p> 8864 * 8865 * @param str the String to swap case, may be null 8866 * @return the changed String, {@code null} if null String input 8867 */ 8868 public static String swapCase(final String str) { 8869 if (isEmpty(str)) { 8870 return str; 8871 } 8872 8873 final int strLen = str.length(); 8874 final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array 8875 int outOffset = 0; 8876 for (int i = 0; i < strLen; ) { 8877 final int oldCodepoint = str.codePointAt(i); 8878 final int newCodePoint; 8879 if (Character.isUpperCase(oldCodepoint)) { 8880 newCodePoint = Character.toLowerCase(oldCodepoint); 8881 } else if (Character.isTitleCase(oldCodepoint)) { 8882 newCodePoint = Character.toLowerCase(oldCodepoint); 8883 } else if (Character.isLowerCase(oldCodepoint)) { 8884 newCodePoint = Character.toUpperCase(oldCodepoint); 8885 } else { 8886 newCodePoint = oldCodepoint; 8887 } 8888 newCodePoints[outOffset++] = newCodePoint; 8889 i += Character.charCount(newCodePoint); 8890 } 8891 return new String(newCodePoints, 0, outOffset); 8892 } 8893 8894 /** 8895 * <p>Converts a {@code CharSequence} into an array of code points.</p> 8896 * 8897 * <p>Valid pairs of surrogate code units will be converted into a single supplementary 8898 * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or 8899 * a low surrogate not preceded by a high surrogate) will be returned as-is.</p> 8900 * 8901 * <pre> 8902 * StringUtils.toCodePoints(null) = null 8903 * StringUtils.toCodePoints("") = [] // empty array 8904 * </pre> 8905 * 8906 * @param str the character sequence to convert 8907 * @return an array of code points 8908 * @since 3.6 8909 */ 8910 public static int[] toCodePoints(final CharSequence str) { 8911 if (str == null) { 8912 return null; 8913 } 8914 if (str.length() == 0) { 8915 return ArrayUtils.EMPTY_INT_ARRAY; 8916 } 8917 8918 final String s = str.toString(); 8919 final int[] result = new int[s.codePointCount(0, s.length())]; 8920 int index = 0; 8921 for (int i = 0; i < result.length; i++) { 8922 result[i] = s.codePointAt(index); 8923 index += Character.charCount(result[i]); 8924 } 8925 return result; 8926 } 8927 8928 /** 8929 * Converts a {@code byte[]} to a String using the specified character encoding. 8930 * 8931 * @param bytes 8932 * the byte array to read from 8933 * @param charset 8934 * the encoding to use, if null then use the platform default 8935 * @return a new String 8936 * @throws NullPointerException 8937 * if {@code bytes} is null 8938 * @since 3.2 8939 * @since 3.3 No longer throws {@link UnsupportedEncodingException}. 8940 */ 8941 public static String toEncodedString(final byte[] bytes, final Charset charset) { 8942 return new String(bytes, Charsets.toCharset(charset)); 8943 } 8944 8945 /** 8946 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner. 8947 * 8948 * @param source A source String or null. 8949 * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null. 8950 * @since 3.10 8951 */ 8952 public static String toRootLowerCase(final String source) { 8953 return source == null ? null : source.toLowerCase(Locale.ROOT); 8954 } 8955 8956 /** 8957 * Converts the given source String as a upper-case using the {@link Locale#ROOT} locale in a null-safe manner. 8958 * 8959 * @param source A source String or null. 8960 * @return the given source String as a upper-case using the {@link Locale#ROOT} locale or null. 8961 * @since 3.10 8962 */ 8963 public static String toRootUpperCase(final String source) { 8964 return source == null ? null : source.toUpperCase(Locale.ROOT); 8965 } 8966 8967 /** 8968 * Converts a {@code byte[]} to a String using the specified character encoding. 8969 * 8970 * @param bytes 8971 * the byte array to read from 8972 * @param charsetName 8973 * the encoding to use, if null then use the platform default 8974 * @return a new String 8975 * @throws UnsupportedEncodingException 8976 * If the named charset is not supported 8977 * @throws NullPointerException 8978 * if the input is null 8979 * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code 8980 * @since 3.1 8981 */ 8982 @Deprecated 8983 public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException { 8984 return charsetName != null ? new String(bytes, charsetName) : new String(bytes, Charset.defaultCharset()); 8985 } 8986 8987 // Trim 8988 //----------------------------------------------------------------------- 8989 /** 8990 * <p>Removes control characters (char <= 32) from both 8991 * ends of this String, handling {@code null} by returning 8992 * {@code null}.</p> 8993 * 8994 * <p>The String is trimmed using {@link String#trim()}. 8995 * Trim removes start and end characters <= 32. 8996 * To strip whitespace use {@link #strip(String)}.</p> 8997 * 8998 * <p>To trim your choice of characters, use the 8999 * {@link #strip(String, String)} methods.</p> 9000 * 9001 * <pre> 9002 * StringUtils.trim(null) = null 9003 * StringUtils.trim("") = "" 9004 * StringUtils.trim(" ") = "" 9005 * StringUtils.trim("abc") = "abc" 9006 * StringUtils.trim(" abc ") = "abc" 9007 * </pre> 9008 * 9009 * @param str the String to be trimmed, may be null 9010 * @return the trimmed string, {@code null} if null String input 9011 */ 9012 public static String trim(final String str) { 9013 return str == null ? null : str.trim(); 9014 } 9015 9016 /** 9017 * <p>Removes control characters (char <= 32) from both 9018 * ends of this String returning an empty String ("") if the String 9019 * is empty ("") after the trim or if it is {@code null}. 9020 * 9021 * <p>The String is trimmed using {@link String#trim()}. 9022 * Trim removes start and end characters <= 32. 9023 * To strip whitespace use {@link #stripToEmpty(String)}.</p> 9024 * 9025 * <pre> 9026 * StringUtils.trimToEmpty(null) = "" 9027 * StringUtils.trimToEmpty("") = "" 9028 * StringUtils.trimToEmpty(" ") = "" 9029 * StringUtils.trimToEmpty("abc") = "abc" 9030 * StringUtils.trimToEmpty(" abc ") = "abc" 9031 * </pre> 9032 * 9033 * @param str the String to be trimmed, may be null 9034 * @return the trimmed String, or an empty String if {@code null} input 9035 * @since 2.0 9036 */ 9037 public static String trimToEmpty(final String str) { 9038 return str == null ? EMPTY : str.trim(); 9039 } 9040 9041 /** 9042 * <p>Removes control characters (char <= 32) from both 9043 * ends of this String returning {@code null} if the String is 9044 * empty ("") after the trim or if it is {@code null}. 9045 * 9046 * <p>The String is trimmed using {@link String#trim()}. 9047 * Trim removes start and end characters <= 32. 9048 * To strip whitespace use {@link #stripToNull(String)}.</p> 9049 * 9050 * <pre> 9051 * StringUtils.trimToNull(null) = null 9052 * StringUtils.trimToNull("") = null 9053 * StringUtils.trimToNull(" ") = null 9054 * StringUtils.trimToNull("abc") = "abc" 9055 * StringUtils.trimToNull(" abc ") = "abc" 9056 * </pre> 9057 * 9058 * @param str the String to be trimmed, may be null 9059 * @return the trimmed String, 9060 * {@code null} if only chars <= 32, empty or null String input 9061 * @since 2.0 9062 */ 9063 public static String trimToNull(final String str) { 9064 final String ts = trim(str); 9065 return isEmpty(ts) ? null : ts; 9066 } 9067 9068 /** 9069 * <p>Truncates a String. This will turn 9070 * "Now is the time for all good men" into "Now is the time for".</p> 9071 * 9072 * <p>Specifically:</p> 9073 * <ul> 9074 * <li>If {@code str} is less than {@code maxWidth} characters 9075 * long, return it.</li> 9076 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li> 9077 * <li>If {@code maxWidth} is less than {@code 0}, throw an 9078 * {@code IllegalArgumentException}.</li> 9079 * <li>In no case will it return a String of length greater than 9080 * {@code maxWidth}.</li> 9081 * </ul> 9082 * 9083 * <pre> 9084 * StringUtils.truncate(null, 0) = null 9085 * StringUtils.truncate(null, 2) = null 9086 * StringUtils.truncate("", 4) = "" 9087 * StringUtils.truncate("abcdefg", 4) = "abcd" 9088 * StringUtils.truncate("abcdefg", 6) = "abcdef" 9089 * StringUtils.truncate("abcdefg", 7) = "abcdefg" 9090 * StringUtils.truncate("abcdefg", 8) = "abcdefg" 9091 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException 9092 * </pre> 9093 * 9094 * @param str the String to truncate, may be null 9095 * @param maxWidth maximum length of result String, must be positive 9096 * @return truncated String, {@code null} if null String input 9097 * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0} 9098 * @since 3.5 9099 */ 9100 public static String truncate(final String str, final int maxWidth) { 9101 return truncate(str, 0, maxWidth); 9102 } 9103 9104 /** 9105 * <p>Truncates a String. This will turn 9106 * "Now is the time for all good men" into "is the time for all".</p> 9107 * 9108 * <p>Works like {@code truncate(String, int)}, but allows you to specify 9109 * a "left edge" offset. 9110 * 9111 * <p>Specifically:</p> 9112 * <ul> 9113 * <li>If {@code str} is less than {@code maxWidth} characters 9114 * long, return it.</li> 9115 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li> 9116 * <li>If {@code maxWidth} is less than {@code 0}, throw an 9117 * {@code IllegalArgumentException}.</li> 9118 * <li>If {@code offset} is less than {@code 0}, throw an 9119 * {@code IllegalArgumentException}.</li> 9120 * <li>In no case will it return a String of length greater than 9121 * {@code maxWidth}.</li> 9122 * </ul> 9123 * 9124 * <pre> 9125 * StringUtils.truncate(null, 0, 0) = null 9126 * StringUtils.truncate(null, 2, 4) = null 9127 * StringUtils.truncate("", 0, 10) = "" 9128 * StringUtils.truncate("", 2, 10) = "" 9129 * StringUtils.truncate("abcdefghij", 0, 3) = "abc" 9130 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij" 9131 * StringUtils.truncate("raspberry peach", 10, 15) = "peach" 9132 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" 9133 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException 9134 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException 9135 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException 9136 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" 9137 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" 9138 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" 9139 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" 9140 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" 9141 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" 9142 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" 9143 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" 9144 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" 9145 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" 9146 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" 9147 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" 9148 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" 9149 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" 9150 * StringUtils.truncate("abcdefghijklmno", 15, 1) = "" 9151 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" 9152 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" 9153 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException 9154 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException 9155 * </pre> 9156 * 9157 * @param str the String to truncate, may be null 9158 * @param offset left edge of source String 9159 * @param maxWidth maximum length of result String, must be positive 9160 * @return truncated String, {@code null} if null String input 9161 * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0} 9162 * @since 3.5 9163 */ 9164 public static String truncate(final String str, final int offset, final int maxWidth) { 9165 if (offset < 0) { 9166 throw new IllegalArgumentException("offset cannot be negative"); 9167 } 9168 if (maxWidth < 0) { 9169 throw new IllegalArgumentException("maxWith cannot be negative"); 9170 } 9171 if (str == null) { 9172 return null; 9173 } 9174 if (offset > str.length()) { 9175 return EMPTY; 9176 } 9177 if (str.length() > maxWidth) { 9178 final int ix = offset + maxWidth > str.length() ? str.length() : offset + maxWidth; 9179 return str.substring(offset, ix); 9180 } 9181 return str.substring(offset); 9182 } 9183 9184 /** 9185 * <p>Uncapitalizes a String, changing the first character to lower case as 9186 * per {@link Character#toLowerCase(int)}. No other characters are changed.</p> 9187 * 9188 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String)}. 9189 * A {@code null} input String returns {@code null}.</p> 9190 * 9191 * <pre> 9192 * StringUtils.uncapitalize(null) = null 9193 * StringUtils.uncapitalize("") = "" 9194 * StringUtils.uncapitalize("cat") = "cat" 9195 * StringUtils.uncapitalize("Cat") = "cat" 9196 * StringUtils.uncapitalize("CAT") = "cAT" 9197 * </pre> 9198 * 9199 * @param str the String to uncapitalize, may be null 9200 * @return the uncapitalized String, {@code null} if null String input 9201 * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String) 9202 * @see #capitalize(String) 9203 * @since 2.0 9204 */ 9205 public static String uncapitalize(final String str) { 9206 final int strLen = length(str); 9207 if (strLen == 0) { 9208 return str; 9209 } 9210 9211 final int firstCodepoint = str.codePointAt(0); 9212 final int newCodePoint = Character.toLowerCase(firstCodepoint); 9213 if (firstCodepoint == newCodePoint) { 9214 // already capitalized 9215 return str; 9216 } 9217 9218 final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array 9219 int outOffset = 0; 9220 newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint 9221 for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) { 9222 final int codepoint = str.codePointAt(inOffset); 9223 newCodePoints[outOffset++] = codepoint; // copy the remaining ones 9224 inOffset += Character.charCount(codepoint); 9225 } 9226 return new String(newCodePoints, 0, outOffset); 9227 } 9228 9229 /** 9230 * <p> 9231 * Unwraps a given string from a character. 9232 * </p> 9233 * 9234 * <pre> 9235 * StringUtils.unwrap(null, null) = null 9236 * StringUtils.unwrap(null, '\0') = null 9237 * StringUtils.unwrap(null, '1') = null 9238 * StringUtils.unwrap("a", 'a') = "a" 9239 * StringUtils.unwrap("aa", 'a') = "" 9240 * StringUtils.unwrap("\'abc\'", '\'') = "abc" 9241 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA" 9242 * StringUtils.unwrap("A", '#') = "A" 9243 * StringUtils.unwrap("#A", '#') = "#A" 9244 * StringUtils.unwrap("A#", '#') = "A#" 9245 * </pre> 9246 * 9247 * @param str 9248 * the String to be unwrapped, can be null 9249 * @param wrapChar 9250 * the character used to unwrap 9251 * @return unwrapped String or the original string 9252 * if it is not quoted properly with the wrapChar 9253 * @since 3.6 9254 */ 9255 public static String unwrap(final String str, final char wrapChar) { 9256 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) { 9257 return str; 9258 } 9259 9260 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) { 9261 final int startIndex = 0; 9262 final int endIndex = str.length() - 1; 9263 9264 return str.substring(startIndex + 1, endIndex); 9265 } 9266 9267 return str; 9268 } 9269 9270 /** 9271 * <p> 9272 * Unwraps a given string from anther string. 9273 * </p> 9274 * 9275 * <pre> 9276 * StringUtils.unwrap(null, null) = null 9277 * StringUtils.unwrap(null, "") = null 9278 * StringUtils.unwrap(null, "1") = null 9279 * StringUtils.unwrap("a", "a") = "a" 9280 * StringUtils.unwrap("aa", "a") = "" 9281 * StringUtils.unwrap("\'abc\'", "\'") = "abc" 9282 * StringUtils.unwrap("\"abc\"", "\"") = "abc" 9283 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB" 9284 * StringUtils.unwrap("A", "#") = "A" 9285 * StringUtils.unwrap("#A", "#") = "#A" 9286 * StringUtils.unwrap("A#", "#") = "A#" 9287 * </pre> 9288 * 9289 * @param str 9290 * the String to be unwrapped, can be null 9291 * @param wrapToken 9292 * the String used to unwrap 9293 * @return unwrapped String or the original string 9294 * if it is not quoted properly with the wrapToken 9295 * @since 3.6 9296 */ 9297 public static String unwrap(final String str, final String wrapToken) { 9298 if (isEmpty(str) || isEmpty(wrapToken) || str.length() == 1) { 9299 return str; 9300 } 9301 9302 if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) { 9303 final int startIndex = str.indexOf(wrapToken); 9304 final int endIndex = str.lastIndexOf(wrapToken); 9305 final int wrapLength = wrapToken.length(); 9306 9307 if (startIndex != -1 && endIndex != -1) { 9308 return str.substring(startIndex + wrapLength, endIndex); 9309 } 9310 } 9311 9312 return str; 9313 } 9314 9315 // Case conversion 9316 //----------------------------------------------------------------------- 9317 /** 9318 * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p> 9319 * 9320 * <p>A {@code null} input String returns {@code null}.</p> 9321 * 9322 * <pre> 9323 * StringUtils.upperCase(null) = null 9324 * StringUtils.upperCase("") = "" 9325 * StringUtils.upperCase("aBc") = "ABC" 9326 * </pre> 9327 * 9328 * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, 9329 * the result of this method is affected by the current locale. 9330 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 9331 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 9332 * 9333 * @param str the String to upper case, may be null 9334 * @return the upper cased String, {@code null} if null String input 9335 */ 9336 public static String upperCase(final String str) { 9337 if (str == null) { 9338 return null; 9339 } 9340 return str.toUpperCase(); 9341 } 9342 9343 /** 9344 * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p> 9345 * 9346 * <p>A {@code null} input String returns {@code null}.</p> 9347 * 9348 * <pre> 9349 * StringUtils.upperCase(null, Locale.ENGLISH) = null 9350 * StringUtils.upperCase("", Locale.ENGLISH) = "" 9351 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 9352 * </pre> 9353 * 9354 * @param str the String to upper case, may be null 9355 * @param locale the locale that defines the case transformation rules, must not be null 9356 * @return the upper cased String, {@code null} if null String input 9357 * @since 2.5 9358 */ 9359 public static String upperCase(final String str, final Locale locale) { 9360 if (str == null) { 9361 return null; 9362 } 9363 return str.toUpperCase(locale); 9364 } 9365 9366 /** 9367 * Returns the string representation of the {@code char} array or null. 9368 * 9369 * @param value the character array. 9370 * @return a String or null 9371 * @see String#valueOf(char[]) 9372 * @since 3.9 9373 */ 9374 public static String valueOf(final char[] value) { 9375 return value == null ? null : String.valueOf(value); 9376 } 9377 9378 /** 9379 * <p> 9380 * Wraps a string with a char. 9381 * </p> 9382 * 9383 * <pre> 9384 * StringUtils.wrap(null, *) = null 9385 * StringUtils.wrap("", *) = "" 9386 * StringUtils.wrap("ab", '\0') = "ab" 9387 * StringUtils.wrap("ab", 'x') = "xabx" 9388 * StringUtils.wrap("ab", '\'') = "'ab'" 9389 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\"" 9390 * </pre> 9391 * 9392 * @param str 9393 * the string to be wrapped, may be {@code null} 9394 * @param wrapWith 9395 * the char that will wrap {@code str} 9396 * @return the wrapped string, or {@code null} if {@code str==null} 9397 * @since 3.4 9398 */ 9399 public static String wrap(final String str, final char wrapWith) { 9400 9401 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9402 return str; 9403 } 9404 9405 return wrapWith + str + wrapWith; 9406 } 9407 9408 /** 9409 * <p> 9410 * Wraps a String with another String. 9411 * </p> 9412 * 9413 * <p> 9414 * A {@code null} input String returns {@code null}. 9415 * </p> 9416 * 9417 * <pre> 9418 * StringUtils.wrap(null, *) = null 9419 * StringUtils.wrap("", *) = "" 9420 * StringUtils.wrap("ab", null) = "ab" 9421 * StringUtils.wrap("ab", "x") = "xabx" 9422 * StringUtils.wrap("ab", "\"") = "\"ab\"" 9423 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\"" 9424 * StringUtils.wrap("ab", "'") = "'ab'" 9425 * StringUtils.wrap("'abcd'", "'") = "''abcd''" 9426 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'" 9427 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\"" 9428 * </pre> 9429 * 9430 * @param str 9431 * the String to be wrapper, may be null 9432 * @param wrapWith 9433 * the String that will wrap str 9434 * @return wrapped String, {@code null} if null String input 9435 * @since 3.4 9436 */ 9437 public static String wrap(final String str, final String wrapWith) { 9438 9439 if (isEmpty(str) || isEmpty(wrapWith)) { 9440 return str; 9441 } 9442 9443 return wrapWith.concat(str).concat(wrapWith); 9444 } 9445 9446 /** 9447 * <p> 9448 * Wraps a string with a char if that char is missing from the start or end of the given string. 9449 * </p> 9450 * 9451 * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p> 9452 * 9453 * <pre> 9454 * StringUtils.wrapIfMissing(null, *) = null 9455 * StringUtils.wrapIfMissing("", *) = "" 9456 * StringUtils.wrapIfMissing("ab", '\0') = "ab" 9457 * StringUtils.wrapIfMissing("ab", 'x') = "xabx" 9458 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'" 9459 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\"" 9460 * StringUtils.wrapIfMissing("/", '/') = "/" 9461 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/" 9462 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/" 9463 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/" 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.5 9472 */ 9473 public static String wrapIfMissing(final String str, final char wrapWith) { 9474 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9475 return str; 9476 } 9477 final boolean wrapStart = str.charAt(0) != wrapWith; 9478 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith; 9479 if (!wrapStart && !wrapEnd) { 9480 return str; 9481 } 9482 9483 final StringBuilder builder = new StringBuilder(str.length() + 2); 9484 if (wrapStart) { 9485 builder.append(wrapWith); 9486 } 9487 builder.append(str); 9488 if (wrapEnd) { 9489 builder.append(wrapWith); 9490 } 9491 return builder.toString(); 9492 } 9493 9494 /** 9495 * <p> 9496 * Wraps a string with a string if that string is missing from the start or end of the given string. 9497 * </p> 9498 * 9499 * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p> 9500 * 9501 * <pre> 9502 * StringUtils.wrapIfMissing(null, *) = null 9503 * StringUtils.wrapIfMissing("", *) = "" 9504 * StringUtils.wrapIfMissing("ab", null) = "ab" 9505 * StringUtils.wrapIfMissing("ab", "x") = "xabx" 9506 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\"" 9507 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\"" 9508 * StringUtils.wrapIfMissing("ab", "'") = "'ab'" 9509 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'" 9510 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'" 9511 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\"" 9512 * StringUtils.wrapIfMissing("/", "/") = "/" 9513 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/" 9514 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/" 9515 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/" 9516 * </pre> 9517 * 9518 * @param str 9519 * the string to be wrapped, may be {@code null} 9520 * @param wrapWith 9521 * the string that will wrap {@code str} 9522 * @return the wrapped string, or {@code null} if {@code str==null} 9523 * @since 3.5 9524 */ 9525 public static String wrapIfMissing(final String str, final String wrapWith) { 9526 if (isEmpty(str) || isEmpty(wrapWith)) { 9527 return str; 9528 } 9529 9530 final boolean wrapStart = !str.startsWith(wrapWith); 9531 final boolean wrapEnd = !str.endsWith(wrapWith); 9532 if (!wrapStart && !wrapEnd) { 9533 return str; 9534 } 9535 9536 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length()); 9537 if (wrapStart) { 9538 builder.append(wrapWith); 9539 } 9540 builder.append(str); 9541 if (wrapEnd) { 9542 builder.append(wrapWith); 9543 } 9544 return builder.toString(); 9545 } 9546 9547 /** 9548 * <p>{@code StringUtils} instances should NOT be constructed in 9549 * standard programming. Instead, the class should be used as 9550 * {@code StringUtils.trim(" foo ");}.</p> 9551 * 9552 * <p>This constructor is public to permit tools that require a JavaBean 9553 * instance to operate.</p> 9554 */ 9555 public StringUtils() { 9556 super(); 9557 } 9558 9559}