[分享]一个String工具类,也许你的项目中会用得到
每次做项目都会遇到字符串的处理,每次都会去写一个StringUtil,完成一些功能。
但其实每次要的功能都差不多:
1.判断类(包括NULL和空串、是否是空白字符串等)
2.默认值
3.去空白(trim)
4.比较
5.字符类型判断(是否只包含数字、字母)
6.大小写转换(首字母大小写等)
7.字符串分割
8.字符串连接
9.字符串查找
10.取子串
11.删除字符
12.字符串比较
下面是一个字符串的工具类,涵盖了上面列的功能,算是比较完整的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 有关字符串处理的工具类。 3 * 4 * <p> 5 * 这个类中的每个方法都可以“安全”地处理<code>null</code>,而不会抛出<code>NullPointerException</code>。 6 * </p> 7 * 8 */ 9 public class StringUtil { 10 /* ============================================================================ */ 11 /* 常量和singleton。 */ 12 /* ============================================================================ */ 13 14 /** 空字符串。 */ 15 public static final String EMPTY_STRING = ""; 16 17 /* ============================================================================ */ 18 /* 判空函数。 */ 19 /* */ 20 /* 以下方法用来判定一个字符串是否为: */ 21 /* 1. null */ 22 /* 2. empty - "" */ 23 /* 3. blank - "全部是空白" - 空白由Character.isWhitespace所定义。 */ 24 /* ============================================================================ */ 25 26 /** 27 * 检查字符串是否为<code>null</code>或空字符串<code>""</code>。 28 * <pre> 29 * StringUtil.isEmpty(null) = true 30 * StringUtil.isEmpty("") = true 31 * StringUtil.isEmpty(" ") = false 32 * StringUtil.isEmpty("bob") = false 33 * StringUtil.isEmpty(" bob ") = false 34 * </pre> 35 * 36 * @param str 要检查的字符串 37 * 38 * @return 如果为空, 则返回<code>true</code> 39 */ 40 public static boolean isEmpty(String str) { 41 return ((str == null) || (str.length() == 0)); 42 } 43 44 /** 45 * 检查字符串是否不是<code>null</code>和空字符串<code>""</code>。 46 * <pre> 47 * StringUtil.isEmpty(null) = false 48 * StringUtil.isEmpty("") = false 49 * StringUtil.isEmpty(" ") = true 50 * StringUtil.isEmpty("bob") = true 51 * StringUtil.isEmpty(" bob ") = true 52 * </pre> 53 * 54 * @param str 要检查的字符串 55 * 56 * @return 如果不为空, 则返回<code>true</code> 57 */ 58 public static boolean isNotEmpty(String str) { 59 return ((str != null) && (str.length() > 0)); 60 } 61 62 /** 63 * 检查字符串是否是空白:<code>null</code>、空字符串<code>""</code>或只有空白字符。 64 * <pre> 65 * StringUtil.isBlank(null) = true 66 * StringUtil.isBlank("") = true 67 * StringUtil.isBlank(" ") = true 68 * StringUtil.isBlank("bob") = false 69 * StringUtil.isBlank(" bob ") = false 70 * </pre> 71 * 72 * @param str 要检查的字符串 73 * 74 * @return 如果为空白, 则返回<code>true</code> 75 */ 76 public static boolean isBlank(String str) { 77 int length; 78 79 if ((str == null) || ((length = str.length()) == 0)) { 80 return true; 81 } 82 83 for (int i = 0; i < length; i++) { 84 if (!Character.isWhitespace(str.charAt(i))) { 85 return false; 86 } 87 } 88 89 return true; 90 } 91 92 /** 93 * 检查字符串是否不是空白:<code>null</code>、空字符串<code>""</code>或只有空白字符。 94 * <pre> 95 * StringUtil.isBlank(null) = false 96 * StringUtil.isBlank("") = false 97 * StringUtil.isBlank(" ") = false 98 * StringUtil.isBlank("bob") = true 99 * StringUtil.isBlank(" bob ") = true 100 * </pre> 101 * 102 * @param str 要检查的字符串 103 * 104 * @return 如果为空白, 则返回<code>true</code> 105 */ 106 public static boolean isNotBlank(String str) { 107 int length; 108 109 if ((str == null) || ((length = str.length()) == 0)) { 110 return false; 111 } 112 113 for (int i = 0; i < length; i++) { 114 if (!Character.isWhitespace(str.charAt(i))) { 115 return true; 116 } 117 } 118 119 return false; 120 } 121 122 /* ============================================================================ */ 123 /* 默认值函数。 */ 124 /* */ 125 /* 当字符串为null、empty或blank时,将字符串转换成指定的默认字符串。 */ 126 /* ============================================================================ */ 127 128 /** 129 * 如果字符串是<code>null</code>,则返回空字符串<code>""</code>,否则返回字符串本身。 130 * <pre> 131 * StringUtil.defaultIfNull(null) = "" 132 * StringUtil.defaultIfNull("") = "" 133 * StringUtil.defaultIfNull(" ") = " " 134 * StringUtil.defaultIfNull("bat") = "bat" 135 * </pre> 136 * 137 * @param str 要转换的字符串 138 * 139 * @return 字符串本身或空字符串<code>""</code> 140 */ 141 public static String defaultIfNull(String str) { 142 return (str == null) ? EMPTY_STRING : str; 143 } 144 145 /** 146 * 如果字符串是<code>null</code>,则返回指定默认字符串,否则返回字符串本身。 147 * <pre> 148 * StringUtil.defaultIfNull(null, "default") = "default" 149 * StringUtil.defaultIfNull("", "default") = "" 150 * StringUtil.defaultIfNull(" ", "default") = " " 151 * StringUtil.defaultIfNull("bat", "default") = "bat" 152 * </pre> 153 * 154 * @param str 要转换的字符串 155 * @param defaultStr 默认字符串 156 * 157 * @return 字符串本身或指定的默认字符串 158 */ 159 public static String defaultIfNull(String str, String defaultStr) { 160 return (str == null) ? defaultStr : str; 161 } 162 163 /** 164 * 如果字符串是<code>null</code>或空字符串<code>""</code>,则返回空字符串<code>""</code>,否则返回字符串本身。 165 * 166 * <p> 167 * 此方法实际上和<code>defaultIfNull(String)</code>等效。 168 * <pre> 169 * StringUtil.defaultIfEmpty(null) = "" 170 * StringUtil.defaultIfEmpty("") = "" 171 * StringUtil.defaultIfEmpty(" ") = " " 172 * StringUtil.defaultIfEmpty("bat") = "bat" 173 * </pre> 174 * </p> 175 * 176 * @param str 要转换的字符串 177 * 178 * @return 字符串本身或空字符串<code>""</code> 179 */ 180 public static String defaultIfEmpty(String str) { 181 return (str == null) ? EMPTY_STRING : str; 182 } 183 184 /** 185 * 如果字符串是<code>null</code>或空字符串<code>""</code>,则返回指定默认字符串,否则返回字符串本身。 186 * <pre> 187 * StringUtil.defaultIfEmpty(null, "default") = "default" 188 * StringUtil.defaultIfEmpty("", "default") = "default" 189 * StringUtil.defaultIfEmpty(" ", "default") = " " 190 * StringUtil.defaultIfEmpty("bat", "default") = "bat" 191 * </pre> 192 * 193 * @param str 要转换的字符串 194 * @param defaultStr 默认字符串 195 * 196 * @return 字符串本身或指定的默认字符串 197 */ 198 public static String defaultIfEmpty(String str, String defaultStr) { 199 return ((str == null) || (str.length() == 0)) ? defaultStr : str; 200 } 201 202 /** 203 * 如果字符串是空白:<code>null</code>、空字符串<code>""</code>或只有空白字符,则返回空字符串<code>""</code>,否则返回字符串本身。 204 * <pre> 205 * StringUtil.defaultIfBlank(null) = "" 206 * StringUtil.defaultIfBlank("") = "" 207 * StringUtil.defaultIfBlank(" ") = "" 208 * StringUtil.defaultIfBlank("bat") = "bat" 209 * </pre> 210 * 211 * @param str 要转换的字符串 212 * 213 * @return 字符串本身或空字符串<code>""</code> 214 */ 215 public static String defaultIfBlank(String str) { 216 return isBlank(str) ? EMPTY_STRING : str; 217 } 218 219 /** 220 * 如果字符串是<code>null</code>或空字符串<code>""</code>,则返回指定默认字符串,否则返回字符串本身。 221 * <pre> 222 * StringUtil.defaultIfBlank(null, "default") = "default" 223 * StringUtil.defaultIfBlank("", "default") = "default" 224 * StringUtil.defaultIfBlank(" ", "default") = "default" 225 * StringUtil.defaultIfBlank("bat", "default") = "bat" 226 * </pre> 227 * 228 * @param str 要转换的字符串 229 * @param defaultStr 默认字符串 230 * 231 * @return 字符串本身或指定的默认字符串 232 */ 233 public static String defaultIfBlank(String str, String defaultStr) { 234 return isBlank(str) ? defaultStr : str; 235 } 236 237 /* ============================================================================ */ 238 /* 去空白(或指定字符)的函数。 */ 239 /* */ 240 /* 以下方法用来除去一个字串中的空白或指定字符。 */ 241 /* ============================================================================ */ 242 243 /** 244 * 除去字符串头尾部的空白,如果字符串是<code>null</code>,依然返回<code>null</code>。 245 * 246 * <p> 247 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code>来判定空白, 248 * 因而可以除去英文字符集之外的其它空白,如中文空格。 249 * <pre> 250 * StringUtil.trim(null) = null 251 * StringUtil.trim("") = "" 252 * StringUtil.trim(" ") = "" 253 * StringUtil.trim("abc") = "abc" 254 * StringUtil.trim(" abc ") = "abc" 255 * </pre> 256 * </p> 257 * 258 * @param str 要处理的字符串 259 * 260 * @return 除去空白的字符串,如果原字串为<code>null</code>,则返回<code>null</code> 261 */ 262 public static String trim(String str) { 263 return trim(str, null, 0); 264 } 265 266 /** 267 * 除去字符串头尾部的指定字符,如果字符串是<code>null</code>,依然返回<code>null</code>。 268 * <pre> 269 * StringUtil.trim(null, *) = null 270 * StringUtil.trim("", *) = "" 271 * StringUtil.trim("abc", null) = "abc" 272 * StringUtil.trim(" abc", null) = "abc" 273 * StringUtil.trim("abc ", null) = "abc" 274 * StringUtil.trim(" abc ", null) = "abc" 275 * StringUtil.trim(" abcyx", "xyz") = " abc" 276 * </pre> 277 * 278 * @param str 要处理的字符串 279 * @param stripChars 要除去的字符,如果为<code>null</code>表示除去空白字符 280 * 281 * @return 除去指定字符后的的字符串,如果原字串为<code>null</code>,则返回<code>null</code> 282 */ 283 public static String trim(String str, String stripChars) { 284 return trim(str, stripChars, 0); 285 } 286 287 /** 288 * 除去字符串头部的空白,如果字符串是<code>null</code>,则返回<code>null</code>。 289 * 290 * <p> 291 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code>来判定空白, 292 * 因而可以除去英文字符集之外的其它空白,如中文空格。 293 * <pre> 294 * StringUtil.trimStart(null) = null 295 * StringUtil.trimStart("") = "" 296 * StringUtil.trimStart("abc") = "abc" 297 * StringUtil.trimStart(" abc") = "abc" 298 * StringUtil.trimStart("abc ") = "abc " 299 * StringUtil.trimStart(" abc ") = "abc " 300 * </pre> 301 * </p> 302 * 303 * @param str 要处理的字符串 304 * 305 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回<code>null</code> 306 */ 307 public static String trimStart(String str) { 308 return trim(str, null, -1); 309 } 310 311 /** 312 * 除去字符串头部的指定字符,如果字符串是<code>null</code>,依然返回<code>null</code>。 313 * <pre> 314 * StringUtil.trimStart(null, *) = null 315 * StringUtil.trimStart("", *) = "" 316 * StringUtil.trimStart("abc", "") = "abc" 317 * StringUtil.trimStart("abc", null) = "abc" 318 * StringUtil.trimStart(" abc", null) = "abc" 319 * StringUtil.trimStart("abc ", null) = "abc " 320 * StringUtil.trimStart(" abc ", null) = "abc " 321 * StringUtil.trimStart("yxabc ", "xyz") = "abc " 322 * </pre> 323 * 324 * @param str 要处理的字符串 325 * @param stripChars 要除去的字符,如果为<code>null</code>表示除去空白字符 326 * 327 * @return 除去指定字符后的的字符串,如果原字串为<code>null</code>,则返回<code>null</code> 328 */ 329 public static String trimStart(String str, String stripChars) { 330 return trim(str, stripChars, -1); 331 } 332 333 /** 334 * 除去字符串尾部的空白,如果字符串是<code>null</code>,则返回<code>null</code>。 335 * 336 * <p> 337 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code>来判定空白, 338 * 因而可以除去英文字符集之外的其它空白,如中文空格。 339 * <pre> 340 * StringUtil.trimEnd(null) = null 341 * StringUtil.trimEnd("") = "" 342 * StringUtil.trimEnd("abc") = "abc" 343 * StringUtil.trimEnd(" abc") = " abc" 344 * StringUtil.trimEnd("abc ") = "abc" 345 * StringUtil.trimEnd(" abc ") = " abc" 346 * </pre> 347 * </p> 348 * 349 * @param str 要处理的字符串 350 * 351 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回<code>null</code> 352 */ 353 public static String trimEnd(String str) { 354 return trim(str, null, 1); 355 } 356 357 /** 358 * 除去字符串尾部的指定字符,如果字符串是<code>null</code>,依然返回<code>null</code>。 359 * <pre> 360 * StringUtil.trimEnd(null, *) = null 361 * StringUtil.trimEnd("", *) = "" 362 * StringUtil.trimEnd("abc", "") = "abc" 363 * StringUtil.trimEnd("abc", null) = "abc" 364 * StringUtil.trimEnd(" abc", null) = " abc" 365 * StringUtil.trimEnd("abc ", null) = "abc" 366 * StringUtil.trimEnd(" abc ", null) = " abc" 367 * StringUtil.trimEnd(" abcyx", "xyz") = " abc" 368 * </pre> 369 * 370 * @param str 要处理的字符串 371 * @param stripChars 要除去的字符,如果为<code>null</code>表示除去空白字符 372 * 373 * @return 除去指定字符后的的字符串,如果原字串为<code>null</code>,则返回<code>null</code> 374 */ 375 public static String trimEnd(String str, String stripChars) { 376 return trim(str, stripChars, 1); 377 } 378 379 /** 380 * 除去字符串头尾部的空白,如果结果字符串是空字符串<code>""</code>,则返回<code>null</code>。 381 * 382 * <p> 383 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code>来判定空白, 384 * 因而可以除去英文字符集之外的其它空白,如中文空格。 385 * <pre> 386 * StringUtil.trimToNull(null) = null 387 * StringUtil.trimToNull("") = null 388 * StringUtil.trimToNull(" ") = null 389 * StringUtil.trimToNull("abc") = "abc" 390 * StringUtil.trimToNull(" abc ") = "abc" 391 * </pre> 392 * </p> 393 * 394 * @param str 要处理的字符串 395 * 396 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回<code>null</code> 397 */ 398 public static String trimToNull(String str) { 399 return trimToNull(str, null); 400 } 401 402 /** 403 * 除去字符串头尾部的空白,如果结果字符串是空字符串<code>""</code>,则返回<code>null</code>。 404 * 405 * <p> 406 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code>来判定空白, 407 * 因而可以除去英文字符集之外的其它空白,如中文空格。 408 * <pre> 409 * StringUtil.trim(null, *) = null 410 * StringUtil.trim("", *) = null 411 * StringUtil.trim("abc", null) = "abc" 412 * StringUtil.trim(" abc", null) = "abc" 413 * StringUtil.trim("abc ", null) = "abc" 414 * StringUtil.trim(" abc ", null) = "abc" 415 * StringUtil.trim(" abcyx", "xyz") = " abc" 416 * </pre> 417 * </p> 418 * 419 * @param str 要处理的字符串 420 * @param stripChars 要除去的字符,如果为<code>null</code>表示除去空白字符 421 * 422 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回<code>null</code> 423 */ 424 public static String trimToNull(String str, String stripChars) { 425 String result = trim(str, stripChars); 426 427 if ((result == null) || (result.length() == 0)) { 428 return null; 429 } 430 431 return result; 432 } 433 434 /** 435 * 除去字符串头尾部的空白,如果字符串是<code>null</code>,则返回空字符串<code>""</code>。 436 * 437 * <p> 438 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code>来判定空白, 439 * 因而可以除去英文字符集之外的其它空白,如中文空格。 440 * <pre> 441 * StringUtil.trimToEmpty(null) = "" 442 * StringUtil.trimToEmpty("") = "" 443 * StringUtil.trimToEmpty(" ") = "" 444 * StringUtil.trimToEmpty("abc") = "abc" 445 * StringUtil.trimToEmpty(" abc ") = "abc" 446 * </pre> 447 * </p> 448 * 449 * @param str 要处理的字符串 450 * 451 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回<code>null</code> 452 */ 453 public static String trimToEmpty(String str) { 454 return trimToEmpty(str, null); 455 } 456 457 /** 458 * 除去字符串头尾部的空白,如果字符串是<code>null</code>,则返回空字符串<code>""</code>。 459 * 460 * <p> 461 * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code>来判定空白, 462 * 因而可以除去英文字符集之外的其它空白,如中文空格。 463 * <pre> 464 * StringUtil.trim(null, *) = "" 465 * StringUtil.trim("", *) = "" 466 * StringUtil.trim("abc", null) = "abc" 467 * StringUtil.trim(" abc", null) = "abc" 468 * StringUtil.trim("abc ", null) = "abc" 469 * StringUtil.trim(" abc ", null) = "abc" 470 * StringUtil.trim(" abcyx", "xyz") = " abc" 471 * </pre> 472 * </p> 473 * 474 * @param str 要处理的字符串 475 * 476 * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回<code>null</code> 477 */ 478 public static String trimToEmpty(String str, String stripChars) { 479 String result = trim(str, stripChars); 480 481 if (result == null) { 482 return EMPTY_STRING; 483 } 484 485 return result; 486 } 487 488 /** 489 * 除去字符串头尾部的指定字符,如果字符串是<code>null</code>,依然返回<code>null</code>。 490 * <pre> 491 * StringUtil.trim(null, *) = null 492 * StringUtil.trim("", *) = "" 493 * StringUtil.trim("abc", null) = "abc" 494 * StringUtil.trim(" abc", null) = "abc" 495 * StringUtil.trim("abc ", null) = "abc" 496 * StringUtil.trim(" abc ", null) = "abc" 497 * StringUtil.trim(" abcyx", "xyz") = " abc" 498 * </pre> 499 * 500 * @param str 要处理的字符串 501 * @param stripChars 要除去的字符,如果为<code>null</code>表示除去空白字符 502 * @param mode <code>-1</code>表示trimStart,<code>0</code>表示trim全部,<code>1</code>表示trimEnd 503 * 504 * @return 除去指定字符后的的字符串,如果原字串为<code>null</code>,则返回<code>null</code> 505 */ 506 private static String trim(String str, String stripChars, int mode) { 507 if (str == null) { 508 return null; 509 } 510 511 int length = str.length(); 512 int start = 0; 513 int end = length; 514 515 // 扫描字符串头部 516 if (mode <= 0) { 517 if (stripChars == null) { 518 while ((start < end) && (Character.isWhitespace(str.charAt(start)))) { 519 start++; 520 } 521 } else if (stripChars.length() == 0) { 522 return str; 523 } else { 524 while ((start < end) && (stripChars.indexOf(str.charAt(start)) != -1)) { 525 start++; 526 } 527 } 528 } 529 530 // 扫描字符串尾部 531 if (mode >= 0) { 532 if (stripChars == null) { 533 while ((start < end) && (Character.isWhitespace(str.charAt(end - 1)))) { 534 end--; 535 } 536 } else if (stripChars.length() == 0) { 537 return str; 538 } else { 539 while ((start < end) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) { 540 end--; 541 } 542 } 543 } 544 545 if ((start > 0) || (end < length)) { 546 return str.substring(start, end); 547 } 548 549 return str; 550 } 551 552 /* ============================================================================ */ 553 /* 比较函数。 */ 554 /* */ 555 /* 以下方法用来比较两个字符串是否相同。 */ 556 /* ============================================================================ */ 557 558 /** 559 * 比较两个字符串(大小写敏感)。 560 * <pre> 561 * StringUtil.equals(null, null) = true 562 * StringUtil.equals(null, "abc") = false 563 * StringUtil.equals("abc", null) = false 564 * StringUtil.equals("abc", "abc") = true 565 * StringUtil.equals("abc", "ABC") = false 566 * </pre> 567 * 568 * @param str1 要比较的字符串1 569 * @param str2 要比较的字符串2 570 * 571 * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code> 572 */ 573 public static boolean equals(String str1, String str2) { 574 if (str1 == null) { 575 return str2 == null; 576 } 577 578 return str1.equals(str2); 579 } 580 581 /** 582 * 比较两个字符串(大小写不敏感)。 583 * <pre> 584 * StringUtil.equalsIgnoreCase(null, null) = true 585 * StringUtil.equalsIgnoreCase(null, "abc") = false 586 * StringUtil.equalsIgnoreCase("abc", null) = false 587 * StringUtil.equalsIgnoreCase("abc", "abc") = true 588 * StringUtil.equalsIgnoreCase("abc", "ABC") = true 589 * </pre> 590 * 591 * @param str1 要比较的字符串1 592 * @param str2 要比较的字符串2 593 * 594 * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code> 595 */ 596 public static boolean equalsIgnoreCase(String str1, String str2) { 597 if (str1 == null) { 598 return str2 == null; 599 } 600 601 return str1.equalsIgnoreCase(str2); 602 } 603 604 /* ============================================================================ */ 605 /* 字符串类型判定函数。 */ 606 /* */ 607 /* 判定字符串的类型是否为:字母、数字、空白等 */ 608 /* ============================================================================ */ 609 610 /** 611 * 判断字符串是否只包含unicode字母。 612 * 613 * <p> 614 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 615 * </p> 616 * <pre> 617 * StringUtil.isAlpha(null) = false 618 * StringUtil.isAlpha("") = true 619 * StringUtil.isAlpha(" ") = false 620 * StringUtil.isAlpha("abc") = true 621 * StringUtil.isAlpha("ab2c") = false 622 * StringUtil.isAlpha("ab-c") = false 623 * </pre> 624 * 625 * @param str 要检查的字符串 626 * 627 * @return 如果字符串非<code>null</code>并且全由unicode字母组成,则返回<code>true</code> 628 */ 629 public static boolean isAlpha(String str) { 630 if (str == null) { 631 return false; 632 } 633 634 int length = str.length(); 635 636 for (int i = 0; i < length; i++) { 637 if (!Character.isLetter(str.charAt(i))) { 638 return false; 639 } 640 } 641 642 return true; 643 } 644 645 /** 646 * 判断字符串是否只包含unicode字母和空格<code>' '</code>。 647 * 648 * <p> 649 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 650 * </p> 651 * <pre> 652 * StringUtil.isAlphaSpace(null) = false 653 * StringUtil.isAlphaSpace("") = true 654 * StringUtil.isAlphaSpace(" ") = true 655 * StringUtil.isAlphaSpace("abc") = true 656 * StringUtil.isAlphaSpace("ab c") = true 657 * StringUtil.isAlphaSpace("ab2c") = false 658 * StringUtil.isAlphaSpace("ab-c") = false 659 * </pre> 660 * 661 * @param str 要检查的字符串 662 * 663 * @return 如果字符串非<code>null</code>并且全由unicode字母和空格组成,则返回<code>true</code> 664 */ 665 public static boolean isAlphaSpace(String str) { 666 if (str == null) { 667 return false; 668 } 669 670 int length = str.length(); 671 672 for (int i = 0; i < length; i++) { 673 if (!Character.isLetter(str.charAt(i)) && (str.charAt(i) != ' ')) { 674 return false; 675 } 676 } 677 678 return true; 679 } 680 681 /** 682 * 判断字符串是否只包含unicode字母和数字。 683 * 684 * <p> 685 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 686 * </p> 687 * <pre> 688 * StringUtil.isAlphanumeric(null) = false 689 * StringUtil.isAlphanumeric("") = true 690 * StringUtil.isAlphanumeric(" ") = false 691 * StringUtil.isAlphanumeric("abc") = true 692 * StringUtil.isAlphanumeric("ab c") = false 693 * StringUtil.isAlphanumeric("ab2c") = true 694 * StringUtil.isAlphanumeric("ab-c") = false 695 * </pre> 696 * 697 * @param str 要检查的字符串 698 * 699 * @return 如果字符串非<code>null</code>并且全由unicode字母数字组成,则返回<code>true</code> 700 */ 701 public static boolean isAlphanumeric(String str) { 702 if (str == null) { 703 return false; 704 } 705 706 int length = str.length(); 707 708 for (int i = 0; i < length; i++) { 709 if (!Character.isLetterOrDigit(str.charAt(i))) { 710 return false; 711 } 712 } 713 714 return true; 715 } 716 717 /** 718 * 判断字符串是否只包含unicode字母数字和空格<code>' '</code>。 719 * 720 * <p> 721 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 722 * </p> 723 * <pre> 724 * StringUtil.isAlphanumericSpace(null) = false 725 * StringUtil.isAlphanumericSpace("") = true 726 * StringUtil.isAlphanumericSpace(" ") = true 727 * StringUtil.isAlphanumericSpace("abc") = true 728 * StringUtil.isAlphanumericSpace("ab c") = true 729 * StringUtil.isAlphanumericSpace("ab2c") = true 730 * StringUtil.isAlphanumericSpace("ab-c") = false 731 * </pre> 732 * 733 * @param str 要检查的字符串 734 * 735 * @return 如果字符串非<code>null</code>并且全由unicode字母数字和空格组成,则返回<code>true</code> 736 */ 737 public static boolean isAlphanumericSpace(String str) { 738 if (str == null) { 739 return false; 740 } 741 742 int length = str.length(); 743 744 for (int i = 0; i < length; i++) { 745 if (!Character.isLetterOrDigit(str.charAt(i)) && (str.charAt(i) != ' ')) { 746 return false; 747 } 748 } 749 750 return true; 751 } 752 753 /** 754 * 判断字符串是否只包含unicode数字。 755 * 756 * <p> 757 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 758 * </p> 759 * <pre> 760 * StringUtil.isNumeric(null) = false 761 * StringUtil.isNumeric("") = true 762 * StringUtil.isNumeric(" ") = false 763 * StringUtil.isNumeric("123") = true 764 * StringUtil.isNumeric("12 3") = false 765 * StringUtil.isNumeric("ab2c") = false 766 * StringUtil.isNumeric("12-3") = false 767 * StringUtil.isNumeric("12.3") = false 768 * </pre> 769 * 770 * @param str 要检查的字符串 771 * 772 * @return 如果字符串非<code>null</code>并且全由unicode数字组成,则返回<code>true</code> 773 */ 774 public static boolean isNumeric(String str) { 775 if (str == null) { 776 return false; 777 } 778 779 int length = str.length(); 780 781 for (int i = 0; i < length; i++) { 782 if (!Character.isDigit(str.charAt(i))) { 783 return false; 784 } 785 } 786 787 return true; 788 } 789 790 /** 791 * 判断字符串是否只包含unicode数字,包括小数。 792 * 793 * <p> 794 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 795 * </p> 796 * <pre> 797 * StringUtil.isNumeric(null) = false 798 * StringUtil.isNumeric("") = false 799 * StringUtil.isNumeric(" ") = false 800 * StringUtil.isNumeric("123") = true 801 * StringUtil.isNumeric("12 3") = false 802 * StringUtil.isNumeric("ab2c") = false 803 * StringUtil.isNumeric("12-3") = false 804 * StringUtil.isNumeric("12.3") = true 805 * </pre> 806 * 807 * @param str 要检查的字符串 808 * 809 * @return 如果字符串非<code>null</code>并且全由unicode数字组成,则返回<code>true</code> 810 */ 811 public static boolean isNumber(String str) { 812 if (isBlank(str)) { 813 return false; 814 } 815 int index = str.indexOf("."); 816 if (index < 0) { 817 return isNumeric(str); 818 } else { 819 String num1 = str.substring(0, index); 820 String num2 = str.substring(index + 1); 821 return isNumeric(num1) && isNumeric(num2); 822 } 823 } 824 825 826 /** 827 * 判断字符串是否只包含unicode数字和空格<code>' '</code>。 828 * 829 * <p> 830 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 831 * </p> 832 * <pre> 833 * StringUtil.isNumericSpace(null) = false 834 * StringUtil.isNumericSpace("") = true 835 * StringUtil.isNumericSpace(" ") = true 836 * StringUtil.isNumericSpace("123") = true 837 * StringUtil.isNumericSpace("12 3") = true 838 * StringUtil.isNumericSpace("ab2c") = false 839 * StringUtil.isNumericSpace("12-3") = false 840 * StringUtil.isNumericSpace("12.3") = false 841 * </pre> 842 * 843 * @param str 要检查的字符串 844 * 845 * @return 如果字符串非<code>null</code>并且全由unicode数字和空格组成,则返回<code>true</code> 846 */ 847 public static boolean isNumericSpace(String str) { 848 if (str == null) { 849 return false; 850 } 851 852 int length = str.length(); 853 854 for (int i = 0; i < length; i++) { 855 if (!Character.isDigit(str.charAt(i)) && (str.charAt(i) != ' ')) { 856 return false; 857 } 858 } 859 860 return true; 861 } 862 863 /** 864 * 判断字符串是否只包含unicode空白。 865 * 866 * <p> 867 * <code>null</code>将返回<code>false</code>,空字符串<code>""</code>将返回<code>true</code>。 868 * </p> 869 * <pre> 870 * StringUtil.isWhitespace(null) = false 871 * StringUtil.isWhitespace("") = true 872 * StringUtil.isWhitespace(" ") = true 873 * StringUtil.isWhitespace("abc") = false 874 * StringUtil.isWhitespace("ab2c") = false 875 * StringUtil.isWhitespace("ab-c") = false 876 * </pre> 877 * 878 * @param str 要检查的字符串 879 * 880 * @return 如果字符串非<code>null</code>并且全由unicode空白组成,则返回<code>true</code> 881 */ 882 public static boolean isWhitespace(String str) { 883 if (str == null) { 884 return false; 885 } 886 887 int length = str.length(); 888 889 for (int i = 0; i < length; i++) { 890 if (!Character.isWhitespace(str.charAt(i))) { 891 return false; 892 } 893 } 894 895 return true; 896 } 897 898 /* ============================================================================ */ 899 /* 大小写转换。 */ 900 /* ============================================================================ */ 901 902 /** 903 * 将字符串转换成大写。 904 * 905 * <p> 906 * 如果字符串是<code>null</code>则返回<code>null</code>。 907 * <pre> 908 * StringUtil.toUpperCase(null) = null 909 * StringUtil.toUpperCase("") = "" 910 * StringUtil.toUpperCase("aBc") = "ABC" 911 * </pre> 912 * </p> 913 * 914 * @param str 要转换的字符串 915 * 916 * @return 大写字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 917 */ 918 public static String toUpperCase(String str) { 919 if (str == null) { 920 return null; 921 } 922 923 return str.toUpperCase(); 924 } 925 926 /** 927 * 将字符串转换成小写。 928 * 929 * <p> 930 * 如果字符串是<code>null</code>则返回<code>null</code>。 931 * <pre> 932 * StringUtil.toLowerCase(null) = null 933 * StringUtil.toLowerCase("") = "" 934 * StringUtil.toLowerCase("aBc") = "abc" 935 * </pre> 936 * </p> 937 * 938 * @param str 要转换的字符串 939 * 940 * @return 大写字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 941 */ 942 public static String toLowerCase(String str) { 943 if (str == null) { 944 return null; 945 } 946 947 return str.toLowerCase(); 948 } 949 950 /** 951 * 将字符串的首字符转成大写(<code>Character.toTitleCase</code>),其它字符不变。 952 * 953 * <p> 954 * 如果字符串是<code>null</code>则返回<code>null</code>。 955 * <pre> 956 * StringUtil.capitalize(null) = null 957 * StringUtil.capitalize("") = "" 958 * StringUtil.capitalize("cat") = "Cat" 959 * StringUtil.capitalize("cAt") = "CAt" 960 * </pre> 961 * </p> 962 * 963 * @param str 要转换的字符串 964 * 965 * @return 首字符为大写的字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 966 */ 967 public static String capitalize(String str) { 968 int strLen; 969 970 if ((str == null) || ((strLen = str.length()) == 0)) { 971 return str; 972 } 973 974 return new StringBuffer(strLen).append(Character.toTitleCase(str.charAt(0))).append( 975 str.substring(1)).toString(); 976 } 977 978 /** 979 * 将字符串的首字符转成小写,其它字符不变。 980 * 981 * <p> 982 * 如果字符串是<code>null</code>则返回<code>null</code>。 983 * <pre> 984 * StringUtil.uncapitalize(null) = null 985 * StringUtil.uncapitalize("") = "" 986 * StringUtil.uncapitalize("Cat") = "cat" 987 * StringUtil.uncapitalize("CAT") = "cAT" 988 * </pre> 989 * </p> 990 * 991 * @param str 要转换的字符串 992 * 993 * @return 首字符为小写的字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 994 */ 995 public static String uncapitalize(String str) { 996 int strLen; 997 998 if ((str == null) || ((strLen = str.length()) == 0)) { 999 return str; 1000 } 1001 1002 return new StringBuffer(strLen).append(Character.toLowerCase(str.charAt(0))).append( 1003 str.substring(1)).toString(); 1004 } 1005 1006 /** 1007 * 反转字符串的大小写。 1008 * 1009 * <p> 1010 * 如果字符串是<code>null</code>则返回<code>null</code>。 1011 * <pre> 1012 * StringUtil.swapCase(null) = null 1013 * StringUtil.swapCase("") = "" 1014 * StringUtil.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 1015 * </pre> 1016 * </p> 1017 * 1018 * @param str 要转换的字符串 1019 * 1020 * @return 大小写被反转的字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 1021 */ 1022 public static String swapCase(String str) { 1023 int strLen; 1024 1025 if ((str == null) || ((strLen = str.length()) == 0)) { 1026 return str; 1027 } 1028 1029 StringBuffer buffer = new StringBuffer(strLen); 1030 1031 char ch = 0; 1032 1033 for (int i = 0; i < strLen; i++) { 1034 ch = str.charAt(i); 1035 1036 if (Character.isUpperCase(ch)) { 1037 ch = Character.toLowerCase(ch); 1038 } else if (Character.isTitleCase(ch)) { 1039 ch = Character.toLowerCase(ch); 1040 } else if (Character.isLowerCase(ch)) { 1041 ch = Character.toUpperCase(ch); 1042 } 1043 1044 buffer.append(ch); 1045 } 1046 1047 return buffer.toString(); 1048 } 1049 1050 /** 1051 * 将字符串转换成camel case。 1052 * 1053 * <p> 1054 * 如果字符串是<code>null</code>则返回<code>null</code>。 1055 * <pre> 1056 * StringUtil.toCamelCase(null) = null 1057 * StringUtil.toCamelCase("") = "" 1058 * StringUtil.toCamelCase("aBc") = "aBc" 1059 * StringUtil.toCamelCase("aBc def") = "aBcDef" 1060 * StringUtil.toCamelCase("aBc def_ghi") = "aBcDefGhi" 1061 * StringUtil.toCamelCase("aBc def_ghi 123") = "aBcDefGhi123" 1062 * </pre> 1063 * </p> 1064 * 1065 * <p> 1066 * 此方法会保留除了下划线和空白以外的所有分隔符。 1067 * </p> 1068 * 1069 * @param str 要转换的字符串 1070 * 1071 * @return camel case字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 1072 */ 1073 public static String toCamelCase(String str) { 1074 return CAMEL_CASE_TOKENIZER.parse(str); 1075 } 1076 1077 /** 1078 * 将字符串转换成pascal case。 1079 * 1080 * <p> 1081 * 如果字符串是<code>null</code>则返回<code>null</code>。 1082 * <pre> 1083 * StringUtil.toPascalCase(null) = null 1084 * StringUtil.toPascalCase("") = "" 1085 * StringUtil.toPascalCase("aBc") = "ABc" 1086 * StringUtil.toPascalCase("aBc def") = "ABcDef" 1087 * StringUtil.toPascalCase("aBc def_ghi") = "ABcDefGhi" 1088 * StringUtil.toPascalCase("aBc def_ghi 123") = "aBcDefGhi123" 1089 * </pre> 1090 * </p> 1091 * 1092 * <p> 1093 * 此方法会保留除了下划线和空白以外的所有分隔符。 1094 * </p> 1095 * 1096 * @param str 要转换的字符串 1097 * 1098 * @return pascal case字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 1099 */ 1100 public static String toPascalCase(String str) { 1101 return PASCAL_CASE_TOKENIZER.parse(str); 1102 } 1103 1104 /** 1105 * 将字符串转换成下划线分隔的大写字符串。 1106 * 1107 * <p> 1108 * 如果字符串是<code>null</code>则返回<code>null</code>。 1109 * <pre> 1110 * StringUtil.toUpperCaseWithUnderscores(null) = null 1111 * StringUtil.toUpperCaseWithUnderscores("") = "" 1112 * StringUtil.toUpperCaseWithUnderscores("aBc") = "A_BC" 1113 * StringUtil.toUpperCaseWithUnderscores("aBc def") = "A_BC_DEF" 1114 * StringUtil.toUpperCaseWithUnderscores("aBc def_ghi") = "A_BC_DEF_GHI" 1115 * StringUtil.toUpperCaseWithUnderscores("aBc def_ghi 123") = "A_BC_DEF_GHI_123" 1116 * StringUtil.toUpperCaseWithUnderscores("__a__Bc__") = "__A__BC__" 1117 * </pre> 1118 * </p> 1119 * 1120 * <p> 1121 * 此方法会保留除了空白以外的所有分隔符。 1122 * </p> 1123 * 1124 * @param str 要转换的字符串 1125 * 1126 * @return 下划线分隔的大写字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 1127 */ 1128 public static String toUpperCaseWithUnderscores(String str) { 1129 return UPPER_CASE_WITH_UNDERSCORES_TOKENIZER.parse(str); 1130 } 1131 1132 /** 1133 * 将字符串转换成下划线分隔的小写字符串。 1134 * 1135 * <p> 1136 * 如果字符串是<code>null</code>则返回<code>null</code>。 1137 * <pre> 1138 * StringUtil.toLowerCaseWithUnderscores(null) = null 1139 * StringUtil.toLowerCaseWithUnderscores("") = "" 1140 * StringUtil.toLowerCaseWithUnderscores("aBc") = "a_bc" 1141 * StringUtil.toLowerCaseWithUnderscores("aBc def") = "a_bc_def" 1142 * StringUtil.toLowerCaseWithUnderscores("aBc def_ghi") = "a_bc_def_ghi" 1143 * StringUtil.toLowerCaseWithUnderscores("aBc def_ghi 123") = "a_bc_def_ghi_123" 1144 * StringUtil.toLowerCaseWithUnderscores("__a__Bc__") = "__a__bc__" 1145 * </pre> 1146 * </p> 1147 * 1148 * <p> 1149 * 此方法会保留除了空白以外的所有分隔符。 1150 * </p> 1151 * 1152 * @param str 要转换的字符串 1153 * 1154 * @return 下划线分隔的小写字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 1155 */ 1156 public static String toLowerCaseWithUnderscores(String str) { 1157 return LOWER_CASE_WITH_UNDERSCORES_TOKENIZER.parse(str); 1158 } 1159 1160 /** 解析单词的解析器。 */ 1161 private static final WordTokenizer CAMEL_CASE_TOKENIZER = new WordTokenizer() { 1162 protected void startSentence( 1163 StringBuffer buffer, 1164 char ch) { 1165 buffer 1166 .append(Character 1167 .toLowerCase(ch)); 1168 } 1169 1170 protected void startWord( 1171 StringBuffer buffer, 1172 char ch) { 1173 if (!isDelimiter(buffer 1174 .charAt(buffer 1175 .length() - 1))) { 1176 buffer 1177 .append(Character 1178 .toUpperCase(ch)); 1179 } else { 1180 buffer 1181 .append(Character 1182 .toLowerCase(ch)); 1183 } 1184 } 1185 1186 protected void inWord( 1187 StringBuffer buffer, 1188 char ch) { 1189 buffer 1190 .append(Character 1191 .toLowerCase(ch)); 1192 } 1193 1194 protected void startDigitSentence( 1195 StringBuffer buffer, 1196 char ch) { 1197 buffer 1198 .append(ch); 1199 } 1200 1201 protected void startDigitWord( 1202 StringBuffer buffer, 1203 char ch) { 1204 buffer 1205 .append(ch); 1206 } 1207 1208 protected void inDigitWord( 1209 StringBuffer buffer, 1210 char ch) { 1211 buffer 1212 .append(ch); 1213 } 1214 1215 protected void inDelimiter( 1216 StringBuffer buffer, 1217 char ch) { 1218 if (ch != UNDERSCORE) { 1219 buffer 1220 .append(ch); 1221 } 1222 } 1223 }; 1224 1225 private static final WordTokenizer PASCAL_CASE_TOKENIZER = new WordTokenizer() { 1226 protected void startSentence( 1227 StringBuffer buffer, 1228 char ch) { 1229 buffer 1230 .append(Character 1231 .toUpperCase(ch)); 1232 } 1233 1234 protected void startWord( 1235 StringBuffer buffer, 1236 char ch) { 1237 buffer 1238 .append(Character 1239 .toUpperCase(ch)); 1240 } 1241 1242 protected void inWord( 1243 StringBuffer buffer, 1244 char ch) { 1245 buffer 1246 .append(Character 1247 .toLowerCase(ch)); 1248 } 1249 1250 protected void startDigitSentence( 1251 StringBuffer buffer, 1252 char ch) { 1253 buffer 1254 .append(ch); 1255 } 1256 1257 protected void startDigitWord( 1258 StringBuffer buffer, 1259 char ch) { 1260 buffer 1261 .append(ch); 1262 } 1263 1264 protected void inDigitWord( 1265 StringBuffer buffer, 1266 char ch) { 1267 buffer 1268 .append(ch); 1269 } 1270 1271 protected void inDelimiter( 1272 StringBuffer buffer, 1273 char ch) { 1274 if (ch != UNDERSCORE) { 1275 buffer 1276 .append(ch); 1277 } 1278 } 1279 }; 1280 1281 private static final WordTokenizer UPPER_CASE_WITH_UNDERSCORES_TOKENIZER = new WordTokenizer() { 1282 protected void startSentence( 1283 StringBuffer buffer, 1284 char ch) { 1285 buffer 1286 .append(Character 1287 .toUpperCase(ch)); 1288 } 1289 1290 protected void startWord( 1291 StringBuffer buffer, 1292 char ch) { 1293 if (!isDelimiter(buffer 1294 .charAt(buffer 1295 .length() - 1))) { 1296 buffer 1297 .append(UNDERSCORE); 1298 } 1299 1300 buffer 1301 .append(Character 1302 .toUpperCase(ch)); 1303 } 1304 1305 protected void inWord( 1306 StringBuffer buffer, 1307 char ch) { 1308 buffer 1309 .append(Character 1310 .toUpperCase(ch)); 1311 } 1312 1313 protected void startDigitSentence( 1314 StringBuffer buffer, 1315 char ch) { 1316 buffer 1317 .append(ch); 1318 } 1319 1320 protected void startDigitWord( 1321 StringBuffer buffer, 1322 char ch) { 1323 if (!isDelimiter(buffer 1324 .charAt(buffer 1325 .length() - 1))) { 1326 buffer 1327 .append(UNDERSCORE); 1328 } 1329 1330 buffer 1331 .append(ch); 1332 } 1333 1334 protected void inDigitWord( 1335 StringBuffer buffer, 1336 char ch) { 1337 buffer 1338 .append(ch); 1339 } 1340 1341 protected void inDelimiter( 1342 StringBuffer buffer, 1343 char ch) { 1344 buffer 1345 .append(ch); 1346 } 1347 }; 1348 1349 private static final WordTokenizer LOWER_CASE_WITH_UNDERSCORES_TOKENIZER = new WordTokenizer() { 1350 protected void startSentence( 1351 StringBuffer buffer, 1352 char ch) { 1353 buffer 1354 .append(Character 1355 .toLowerCase(ch)); 1356 } 1357 1358 protected void startWord( 1359 StringBuffer buffer, 1360 char ch) { 1361 if (!isDelimiter(buffer 1362 .charAt(buffer 1363 .length() - 1))) { 1364 buffer 1365 .append(UNDERSCORE); 1366 } 1367 1368 buffer 1369 .append(Character 1370 .toLowerCase(ch)); 1371 } 1372 1373 protected void inWord( 1374 StringBuffer buffer, 1375 char ch) { 1376 buffer 1377 .append(Character 1378 .toLowerCase(ch)); 1379 } 1380 1381 protected void startDigitSentence( 1382 StringBuffer buffer, 1383 char ch) { 1384 buffer 1385 .append(ch); 1386 } 1387 1388 protected void startDigitWord( 1389 StringBuffer buffer, 1390 char ch) { 1391 if (!isDelimiter(buffer 1392 .charAt(buffer 1393 .length() - 1))) { 1394 buffer 1395 .append(UNDERSCORE); 1396 } 1397 1398 buffer 1399 .append(ch); 1400 } 1401 1402 protected void inDigitWord( 1403 StringBuffer buffer, 1404 char ch) { 1405 buffer 1406 .append(ch); 1407 } 1408 1409 protected void inDelimiter( 1410 StringBuffer buffer, 1411 char ch) { 1412 buffer 1413 .append(ch); 1414 } 1415 }; 1416 1417 /** 1418 * 解析出下列语法所构成的<code>SENTENCE</code>。 1419 * <pre> 1420 * SENTENCE = WORD (DELIMITER* WORD)* 1421 * 1422 * WORD = UPPER_CASE_WORD | LOWER_CASE_WORD | TITLE_CASE_WORD | DIGIT_WORD 1423 * 1424 * UPPER_CASE_WORD = UPPER_CASE_LETTER+ 1425 * LOWER_CASE_WORD = LOWER_CASE_LETTER+ 1426 * TITLE_CASE_WORD = UPPER_CASE_LETTER LOWER_CASE_LETTER+ 1427 * DIGIT_WORD = DIGIT+ 1428 * 1429 * UPPER_CASE_LETTER = Character.isUpperCase() 1430 * LOWER_CASE_LETTER = Character.isLowerCase() 1431 * DIGIT = Character.isDigit() 1432 * NON_LETTER_DIGIT = !Character.isUpperCase() && !Character.isLowerCase() && !Character.isDigit() 1433 * 1434 * DELIMITER = WHITESPACE | NON_LETTER_DIGIT 1435 * </pre> 1436 */ 1437 private abstract static class WordTokenizer { 1438 protected static final char UNDERSCORE = '_'; 1439 1440 /** 1441 * Parse sentence。 1442 */ 1443 public String parse(String str) { 1444 if (StringUtil.isEmpty(str)) { 1445 return str; 1446 } 1447 1448 int length = str.length(); 1449 StringBuffer buffer = new StringBuffer(length); 1450 1451 for (int index = 0; index < length; index++) { 1452 char ch = str.charAt(index); 1453 1454 // 忽略空白。 1455 if (Character.isWhitespace(ch)) { 1456 continue; 1457 } 1458 1459 // 大写字母开始:UpperCaseWord或是TitleCaseWord。 1460 if (Character.isUpperCase(ch)) { 1461 int wordIndex = index + 1; 1462 1463 while (wordIndex < length) { 1464 char wordChar = str.charAt(wordIndex); 1465 1466 if (Character.isUpperCase(wordChar)) { 1467 wordIndex++; 1468 } else if (Character.isLowerCase(wordChar)) { 1469 wordIndex--; 1470 break; 1471 } else { 1472 break; 1473 } 1474 } 1475 1476 // 1. wordIndex == length,说明最后一个字母为大写,以upperCaseWord处理之。 1477 // 2. wordIndex == index,说明index处为一个titleCaseWord。 1478 // 3. wordIndex > index,说明index到wordIndex - 1处全部是大写,以upperCaseWord处理。 1479 if ((wordIndex == length) || (wordIndex > index)) { 1480 index = parseUpperCaseWord(buffer, str, index, wordIndex); 1481 } else { 1482 index = parseTitleCaseWord(buffer, str, index); 1483 } 1484 1485 continue; 1486 } 1487 1488 // 小写字母开始:LowerCaseWord。 1489 if (Character.isLowerCase(ch)) { 1490 index = parseLowerCaseWord(buffer, str, index); 1491 continue; 1492 } 1493 1494 // 数字开始:DigitWord。 1495 if (Character.isDigit(ch)) { 1496 index = parseDigitWord(buffer, str, index); 1497 continue; 1498 } 1499 1500 // 非字母数字开始:Delimiter。 1501 inDelimiter(buffer, ch); 1502 } 1503 1504 return buffer.toString(); 1505 } 1506 1507 private int parseUpperCaseWord(StringBuffer buffer, String str, int index, int length) { 1508 char ch = str.charAt(index++); 1509 1510 // 首字母,必然存在且为大写。 1511 if (buffer.length() == 0) { 1512 startSentence(buffer, ch); 1513 } else { 1514 startWord(buffer, ch); 1515 } 1516 1517 // 后续字母,必为小写。 1518 for (; index < length; index++) { 1519 ch = str.charAt(index); 1520 inWord(buffer, ch); 1521 } 1522 1523 return index - 1; 1524 } 1525 1526 private int parseLowerCaseWord(StringBuffer buffer, String str, int index) { 1527 char ch = str.charAt(index++); 1528 1529 // 首字母,必然存在且为小写。 1530 if (buffer.length() == 0) { 1531 startSentence(buffer, ch); 1532 } else { 1533 startWord(buffer, ch); 1534 } 1535 1536 // 后续字母,必为小写。 1537 int length = str.length(); 1538 1539 for (; index < length; index++) { 1540 ch = str.charAt(index); 1541 1542 if (Character.isLowerCase(ch)) { 1543 inWord(buffer, ch); 1544 } else { 1545 break; 1546 } 1547 } 1548 1549 return index - 1; 1550 } 1551 1552 private int parseTitleCaseWord(StringBuffer buffer, String str, int index) { 1553 char ch = str.charAt(index++); 1554 1555 // 首字母,必然存在且为大写。 1556 if (buffer.length() == 0) { 1557 startSentence(buffer, ch); 1558 } else { 1559 startWord(buffer, ch); 1560 } 1561 1562 // 后续字母,必为小写。 1563 int length = str.length(); 1564 1565 for (; index < length; index++) { 1566 ch = str.charAt(index); 1567 1568 if (Character.isLowerCase(ch)) { 1569 inWord(buffer, ch); 1570 } else { 1571 break; 1572 } 1573 } 1574 1575 return index - 1; 1576 } 1577 1578 private int parseDigitWord(StringBuffer buffer, String str, int index) { 1579 char ch = str.charAt(index++); 1580 1581 // 首字符,必然存在且为数字。 1582 if (buffer.length() == 0) { 1583 startDigitSentence(buffer, ch); 1584 } else { 1585 startDigitWord(buffer, ch); 1586 } 1587 1588 // 后续字符,必为数字。 1589 int length = str.length(); 1590 1591 for (; index < length; index++) { 1592 ch = str.charAt(index); 1593 1594 if (Character.isDigit(ch)) { 1595 inDigitWord(buffer, ch); 1596 } else { 1597 break; 1598 } 1599 } 1600 1601 return index - 1; 1602 } 1603 1604 protected boolean isDelimiter(char ch) { 1605 return !Character.isUpperCase(ch) && !Character.isLowerCase(ch) 1606 && !Character.isDigit(ch); 1607 } 1608 1609 protected abstract void startSentence(StringBuffer buffer, char ch); 1610 1611 protected abstract void startWord(StringBuffer buffer, char ch); 1612 1613 protected abstract void inWord(StringBuffer buffer, char ch); 1614 1615 protected abstract void startDigitSentence(StringBuffer buffer, char ch); 1616 1617 protected abstract void startDigitWord(StringBuffer buffer, char ch); 1618 1619 protected abstract void inDigitWord(StringBuffer buffer, char ch); 1620 1621 protected abstract void inDelimiter(StringBuffer buffer, char ch); 1622 } 1623 1624 /* ============================================================================ */ 1625 /* 字符串分割函数。 */ 1626 /* */ 1627 /* 将字符串按指定分隔符分割。 */ 1628 /* ============================================================================ */ 1629 1630 /** 1631 * 将字符串按空白字符分割。 1632 * 1633 * <p> 1634 * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为<code>null</code>,则返回<code>null</code>。 1635 * <pre> 1636 * StringUtil.split(null) = null 1637 * StringUtil.split("") = [] 1638 * StringUtil.split("abc def") = ["abc", "def"] 1639 * StringUtil.split("abc def") = ["abc", "def"] 1640 * StringUtil.split(" abc ") = ["abc"] 1641 * </pre> 1642 * </p> 1643 * 1644 * @param str 要分割的字符串 1645 * 1646 * @return 分割后的字符串数组,如果原字符串为<code>null</code>,则返回<code>null</code> 1647 */ 1648 public static String[] split(String str) { 1649 return split(str, null, -1); 1650 } 1651 1652 /** 1653 * 将字符串按指定字符分割。 1654 * 1655 * <p> 1656 * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为<code>null</code>,则返回<code>null</code>。 1657 * <pre> 1658 * StringUtil.split(null, *) = null 1659 * StringUtil.split("", *) = [] 1660 * StringUtil.split("a.b.c", '.') = ["a", "b", "c"] 1661 * StringUtil.split("a..b.c", '.') = ["a", "b", "c"] 1662 * StringUtil.split("a:b:c", '.') = ["a:b:c"] 1663 * StringUtil.split("a b c", ' ') = ["a", "b", "c"] 1664 * </pre> 1665 * </p> 1666 * 1667 * @param str 要分割的字符串 1668 * @param separatorChar 分隔符 1669 * 1670 * @return 分割后的字符串数组,如果原字符串为<code>null</code>,则返回<code>null</code> 1671 */ 1672 public static String[] split(String str, char separatorChar) { 1673 if (str == null) { 1674 return null; 1675 } 1676 1677 int length = str.length(); 1678 1679 if (length == 0) { 1680 return ArrayUtil.EMPTY_STRING_ARRAY; 1681 } 1682 1683 List list = new ArrayList(); 1684 int i = 0; 1685 int start = 0; 1686 boolean match = false; 1687 1688 while (i < length) { 1689 if (str.charAt(i) == separatorChar) { 1690 if (match) { 1691 list.add(str.substring(start, i)); 1692 match = false; 1693 } 1694 1695 start = ++i; 1696 continue; 1697 } 1698 1699 match = true; 1700 i++; 1701 } 1702 1703 if (match) { 1704 list.add(str.substring(start, i)); 1705 } 1706 1707 return (String[]) list.toArray(new String[list.size()]); 1708 } 1709 1710 /** 1711 * 将字符串按指定字符分割。 1712 * 1713 * <p> 1714 * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为<code>null</code>,则返回<code>null</code>。 1715 * <pre> 1716 * StringUtil.split(null, *) = null 1717 * StringUtil.split("", *) = [] 1718 * StringUtil.split("abc def", null) = ["abc", "def"] 1719 * StringUtil.split("abc def", " ") = ["abc", "def"] 1720 * StringUtil.split("abc def", " ") = ["abc", "def"] 1721 * StringUtil.split(" ab: cd::ef ", ":") = ["ab", "cd", "ef"] 1722 * StringUtil.split("abc.def", "") = ["abc.def"] 1723 * </pre> 1724 * </p> 1725 * 1726 * @param str 要分割的字符串 1727 * @param separatorChars 分隔符 1728 * 1729 * @return 分割后的字符串数组,如果原字符串为<code>null</code>,则返回<code>null</code> 1730 */ 1731 public static String[] split(String str, String separatorChars) { 1732 return split(str, separatorChars, -1); 1733 } 1734 1735 /** 1736 * 将字符串按指定字符分割。 1737 * 1738 * <p> 1739 * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为<code>null</code>,则返回<code>null</code>。 1740 * <pre> 1741 * StringUtil.split(null, *, *) = null 1742 * StringUtil.split("", *, *) = [] 1743 * StringUtil.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 1744 * StringUtil.split(" ab cd ef ", null, 0) = ["ab", "cd", "ef"] 1745 * StringUtil.split("ab:cd::ef", ":", 0) = ["ab", "cd", "ef"] 1746 * StringUtil.split("ab:cd:ef", ":", 2) = ["ab", "cdef"] 1747 * StringUtil.split("abc.def", "", 2) = ["abc.def"] 1748 * </pre> 1749 * </p> 1750 * 1751 * @param str 要分割的字符串 1752 * @param separatorChars 分隔符 1753 * @param max 返回的数组的最大个数,如果小于等于0,则表示无限制 1754 * 1755 * @return 分割后的字符串数组,如果原字符串为<code>null</code>,则返回<code>null</code> 1756 */ 1757 public static String[] split(String str, String separatorChars, int max) { 1758 if (str == null) { 1759 return null; 1760 } 1761 1762 int length = str.length(); 1763 1764 if (length == 0) { 1765 return ArrayUtil.EMPTY_STRING_ARRAY; 1766 } 1767 1768 List list = new ArrayList(); 1769 int sizePlus1 = 1; 1770 int i = 0; 1771 int start = 0; 1772 boolean match = false; 1773 1774 if (separatorChars == null) { 1775 // null表示使用空白作为分隔符 1776 while (i < length) { 1777 if (Character.isWhitespace(str.charAt(i))) { 1778 if (match) { 1779 if (sizePlus1++ == max) { 1780 i = length; 1781 } 1782 1783 list.add(str.substring(start, i)); 1784 match = false; 1785 } 1786 1787 start = ++i; 1788 continue; 1789 } 1790 1791 match = true; 1792 i++; 1793 } 1794 } else if (separatorChars.length() == 1) { 1795 // 优化分隔符长度为1的情形 1796 char sep = separatorChars.charAt(0); 1797 1798 while (i < length) { 1799 if (str.charAt(i) == sep) { 1800 if (match) { 1801 if (sizePlus1++ == max) { 1802 i = length; 1803 } 1804 1805 list.add(str.substring(start, i)); 1806 match = false; 1807 } 1808 1809 start = ++i; 1810 continue; 1811 } 1812 1813 match = true; 1814 i++; 1815 } 1816 } else { 1817 // 一般情形 1818 while (i < length) { 1819 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 1820 if (match) { 1821 if (sizePlus1++ == max) { 1822 i = length; 1823 } 1824 1825 list.add(str.substring(start, i)); 1826 match = false; 1827 } 1828 1829 start = ++i; 1830 continue; 1831 } 1832 1833 match = true; 1834 i++; 1835 } 1836 } 1837 1838 if (match) { 1839 list.add(str.substring(start, i)); 1840 } 1841 1842 return (String[]) list.toArray(new String[list.size()]); 1843 } 1844 1845 /* ============================================================================ */ 1846 /* 字符串连接函数。 */ 1847 /* */ 1848 /* 将多个对象按指定分隔符连接成字符串。 */ 1849 /* ============================================================================ */ 1850 1851 /** 1852 * 将数组中的元素连接成一个字符串。 1853 * <pre> 1854 * StringUtil.join(null) = null 1855 * StringUtil.join([]) = "" 1856 * StringUtil.join([null]) = "" 1857 * StringUtil.join(["a", "b", "c"]) = "abc" 1858 * StringUtil.join([null, "", "a"]) = "a" 1859 * </pre> 1860 * 1861 * @param array 要连接的数组 1862 * 1863 * @return 连接后的字符串,如果原数组为<code>null</code>,则返回<code>null</code> 1864 */ 1865 public static String join(Object[] array) { 1866 return join(array, null); 1867 } 1868 1869 /** 1870 * 将数组中的元素连接成一个字符串。 1871 * <pre> 1872 * StringUtil.join(null, *) = null 1873 * StringUtil.join([], *) = "" 1874 * StringUtil.join([null], *) = "" 1875 * StringUtil.join(["a", "b", "c"], ';') = "a;b;c" 1876 * StringUtil.join(["a", "b", "c"], null) = "abc" 1877 * StringUtil.join([null, "", "a"], ';') = ";;a" 1878 * </pre> 1879 * 1880 * @param array 要连接的数组 1881 * @param separator 分隔符 1882 * 1883 * @return 连接后的字符串,如果原数组为<code>null</code>,则返回<code>null</code> 1884 */ 1885 public static String join(Object[] array, char separator) { 1886 if (array == null) { 1887 return null; 1888 } 1889 1890 int arraySize = array.length; 1891 int bufSize = (arraySize == 0) ? 0 : ((((array[0] == null) ? 16 : array[0].toString() 1892 .length()) + 1) * arraySize); 1893 StringBuffer buf = new StringBuffer(bufSize); 1894 1895 for (int i = 0; i < arraySize; i++) { 1896 if (i > 0) { 1897 buf.append(separator); 1898 } 1899 1900 if (array[i] != null) { 1901 buf.append(array[i]); 1902 } 1903 } 1904 1905 return buf.toString(); 1906 } 1907 1908 /** 1909 * 将数组中的元素连接成一个字符串。 1910 * <pre> 1911 * StringUtil.join(null, *) = null 1912 * StringUtil.join([], *) = "" 1913 * StringUtil.join([null], *) = "" 1914 * StringUtil.join(["a", "b", "c"], "--") = "a--b--c" 1915 * StringUtil.join(["a", "b", "c"], null) = "abc" 1916 * StringUtil.join(["a", "b", "c"], "") = "abc" 1917 * StringUtil.join([null, "", "a"], ',') = ",,a" 1918 * </pre> 1919 * 1920 * @param array 要连接的数组 1921 * @param separator 分隔符 1922 * 1923 * @return 连接后的字符串,如果原数组为<code>null</code>,则返回<code>null</code> 1924 */ 1925 public static String join(Object[] array, String separator) { 1926 if (array == null) { 1927 return null; 1928 } 1929 1930 if (separator == null) { 1931 separator = EMPTY_STRING; 1932 } 1933 1934 int arraySize = array.length; 1935 1936 // ArraySize == 0: Len = 0 1937 // ArraySize > 0: Len = NofStrings *(len(firstString) + len(separator)) 1938 // (估计大约所有的字符串都一样长) 1939 int bufSize = (arraySize == 0) ? 0 : (arraySize * (((array[0] == null) ? 16 : array[0] 1940 .toString().length()) + ((separator != null) ? separator.length() : 0))); 1941 1942 StringBuffer buf = new StringBuffer(bufSize); 1943 1944 for (int i = 0; i < arraySize; i++) { 1945 if ((separator != null) && (i > 0)) { 1946 buf.append(separator); 1947 } 1948 1949 if (array[i] != null) { 1950 buf.append(array[i]); 1951 } 1952 } 1953 1954 return buf.toString(); 1955 } 1956 1957 /** 1958 * 将<code>Iterator</code>中的元素连接成一个字符串。 1959 * <pre> 1960 * StringUtil.join(null, *) = null 1961 * StringUtil.join([], *) = "" 1962 * StringUtil.join([null], *) = "" 1963 * StringUtil.join(["a", "b", "c"], "--") = "a--b--c" 1964 * StringUtil.join(["a", "b", "c"], null) = "abc" 1965 * StringUtil.join(["a", "b", "c"], "") = "abc" 1966 * StringUtil.join([null, "", "a"], ',') = ",,a" 1967 * </pre> 1968 * 1969 * @param iterator 要连接的<code>Iterator</code> 1970 * @param separator 分隔符 1971 * 1972 * @return 连接后的字符串,如果原数组为<code>null</code>,则返回<code>null</code> 1973 */ 1974 public static String join(Iterator iterator, char separator) { 1975 if (iterator == null) { 1976 return null; 1977 } 1978 1979 StringBuffer buf = new StringBuffer(256); // Java默认值是16, 可能偏小 1980 1981 while (iterator.hasNext()) { 1982 Object obj = iterator.next(); 1983 1984 if (obj != null) { 1985 buf.append(obj); 1986 } 1987 1988 if (iterator.hasNext()) { 1989 buf.append(separator); 1990 } 1991 } 1992 1993 return buf.toString(); 1994 } 1995 1996 /** 1997 * 将<code>Iterator</code>中的元素连接成一个字符串。 1998 * <pre> 1999 * StringUtil.join(null, *) = null 2000 * StringUtil.join([], *) = "" 2001 * StringUtil.join([null], *) = "" 2002 * StringUtil.join(["a", "b", "c"], "--") = "a--b--c" 2003 * StringUtil.join(["a", "b", "c"], null) = "abc" 2004 * StringUtil.join(["a", "b", "c"], "") = "abc" 2005 * StringUtil.join([null, "", "a"], ',') = ",,a" 2006 * </pre> 2007 * 2008 * @param iterator 要连接的<code>Iterator</code> 2009 * @param separator 分隔符 2010 * 2011 * @return 连接后的字符串,如果原数组为<code>null</code>,则返回<code>null</code> 2012 */ 2013 public static String join(Iterator iterator, String separator) { 2014 if (iterator == null) { 2015 return null; 2016 } 2017 2018 StringBuffer buf = new StringBuffer(256); // Java默认值是16, 可能偏小 2019 2020 while (iterator.hasNext()) { 2021 Object obj = iterator.next(); 2022 2023 if (obj != null) { 2024 buf.append(obj); 2025 } 2026 2027 if ((separator != null) && iterator.hasNext()) { 2028 buf.append(separator); 2029 } 2030 } 2031 2032 return buf.toString(); 2033 } 2034 2035 /* ============================================================================ */ 2036 /* 字符串查找函数 —— 字符或字符串。 */ 2037 /* */ 2038 /* 在字符串中查找指定字符或字符串。 */ 2039 /* ============================================================================ */ 2040 2041 /** 2042 * 在字符串中查找指定字符,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2043 * <pre> 2044 * StringUtil.indexOf(null, *) = -1 2045 * StringUtil.indexOf("", *) = -1 2046 * StringUtil.indexOf("aabaabaa", 'a') = 0 2047 * StringUtil.indexOf("aabaabaa", 'b') = 2 2048 * </pre> 2049 * 2050 * @param str 要扫描的字符串 2051 * @param searchChar 要查找的字符 2052 * 2053 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2054 */ 2055 public static int indexOf(String str, char searchChar) { 2056 if ((str == null) || (str.length() == 0)) { 2057 return -1; 2058 } 2059 2060 return str.indexOf(searchChar); 2061 } 2062 2063 /** 2064 * 在字符串中查找指定字符,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2065 * <pre> 2066 * StringUtil.indexOf(null, *, *) = -1 2067 * StringUtil.indexOf("", *, *) = -1 2068 * StringUtil.indexOf("aabaabaa", 'b', 0) = 2 2069 * StringUtil.indexOf("aabaabaa", 'b', 3) = 5 2070 * StringUtil.indexOf("aabaabaa", 'b', 9) = -1 2071 * StringUtil.indexOf("aabaabaa", 'b', -1) = 2 2072 * </pre> 2073 * 2074 * @param str 要扫描的字符串 2075 * @param searchChar 要查找的字符 2076 * @param startPos 开始搜索的索引值,如果小于0,则看作0 2077 * 2078 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2079 */ 2080 public static int indexOf(String str, char searchChar, int startPos) { 2081 if ((str == null) || (str.length() == 0)) { 2082 return -1; 2083 } 2084 2085 return str.indexOf(searchChar, startPos); 2086 } 2087 2088 /** 2089 * 在字符串中查找指定字符串,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2090 * <pre> 2091 * StringUtil.indexOf(null, *) = -1 2092 * StringUtil.indexOf(*, null) = -1 2093 * StringUtil.indexOf("", "") = 0 2094 * StringUtil.indexOf("aabaabaa", "a") = 0 2095 * StringUtil.indexOf("aabaabaa", "b") = 2 2096 * StringUtil.indexOf("aabaabaa", "ab") = 1 2097 * StringUtil.indexOf("aabaabaa", "") = 0 2098 * </pre> 2099 * 2100 * @param str 要扫描的字符串 2101 * @param searchStr 要查找的字符串 2102 * 2103 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2104 */ 2105 public static int indexOf(String str, String searchStr) { 2106 if ((str == null) || (searchStr == null)) { 2107 return -1; 2108 } 2109 2110 return str.indexOf(searchStr); 2111 } 2112 2113 /** 2114 * 在字符串中查找指定字符串,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2115 * <pre> 2116 * StringUtil.indexOf(null, *, *) = -1 2117 * StringUtil.indexOf(*, null, *) = -1 2118 * StringUtil.indexOf("", "", 0) = 0 2119 * StringUtil.indexOf("aabaabaa", "a", 0) = 0 2120 * StringUtil.indexOf("aabaabaa", "b", 0) = 2 2121 * StringUtil.indexOf("aabaabaa", "ab", 0) = 1 2122 * StringUtil.indexOf("aabaabaa", "b", 3) = 5 2123 * StringUtil.indexOf("aabaabaa", "b", 9) = -1 2124 * StringUtil.indexOf("aabaabaa", "b", -1) = 2 2125 * StringUtil.indexOf("aabaabaa", "", 2) = 2 2126 * StringUtil.indexOf("abc", "", 9) = 3 2127 * </pre> 2128 * 2129 * @param str 要扫描的字符串 2130 * @param searchStr 要查找的字符串 2131 * @param startPos 开始搜索的索引值,如果小于0,则看作0 2132 * 2133 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2134 */ 2135 public static int indexOf(String str, String searchStr, int startPos) { 2136 if ((str == null) || (searchStr == null)) { 2137 return -1; 2138 } 2139 2140 // JDK1.3及以下版本的bug:不能正确处理下面的情况 2141 if ((searchStr.length() == 0) && (startPos >= str.length())) { 2142 return str.length(); 2143 } 2144 2145 return str.indexOf(searchStr, startPos); 2146 } 2147 2148 /** 2149 * 在字符串中查找指定字符集合中的字符,并返回第一个匹配的起始索引。 如果字符串为<code>null</code>,则返回<code>-1</code>。 2150 * 如果字符集合为<code>null</code>或空,也返回<code>-1</code>。 2151 * <pre> 2152 * StringUtil.indexOfAny(null, *) = -1 2153 * StringUtil.indexOfAny("", *) = -1 2154 * StringUtil.indexOfAny(*, null) = -1 2155 * StringUtil.indexOfAny(*, []) = -1 2156 * StringUtil.indexOfAny("zzabyycdxx",['z','a']) = 0 2157 * StringUtil.indexOfAny("zzabyycdxx",['b','y']) = 3 2158 * StringUtil.indexOfAny("aba", ['z']) = -1 2159 * </pre> 2160 * 2161 * @param str 要扫描的字符串 2162 * @param searchChars 要搜索的字符集合 2163 * 2164 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2165 */ 2166 public static int indexOfAny(String str, char[] searchChars) { 2167 if ((str == null) || (str.length() == 0) || (searchChars == null) 2168 || (searchChars.length == 0)) { 2169 return -1; 2170 } 2171 2172 for (int i = 0; i < str.length(); i++) { 2173 char ch = str.charAt(i); 2174 2175 for (int j = 0; j < searchChars.length; j++) { 2176 if (searchChars[j] == ch) { 2177 return i; 2178 } 2179 } 2180 } 2181 2182 return -1; 2183 } 2184 2185 /** 2186 * 在字符串中查找指定字符集合中的字符,并返回第一个匹配的起始索引。 如果字符串为<code>null</code>,则返回<code>-1</code>。 2187 * 如果字符集合为<code>null</code>或空,也返回<code>-1</code>。 2188 * <pre> 2189 * StringUtil.indexOfAny(null, *) = -1 2190 * StringUtil.indexOfAny("", *) = -1 2191 * StringUtil.indexOfAny(*, null) = -1 2192 * StringUtil.indexOfAny(*, "") = -1 2193 * StringUtil.indexOfAny("zzabyycdxx", "za") = 0 2194 * StringUtil.indexOfAny("zzabyycdxx", "by") = 3 2195 * StringUtil.indexOfAny("aba","z") = -1 2196 * </pre> 2197 * 2198 * @param str 要扫描的字符串 2199 * @param searchChars 要搜索的字符集合 2200 * 2201 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2202 */ 2203 public static int indexOfAny(String str, String searchChars) { 2204 if ((str == null) || (str.length() == 0) || (searchChars == null) 2205 || (searchChars.length() == 0)) { 2206 return -1; 2207 } 2208 2209 for (int i = 0; i < str.length(); i++) { 2210 char ch = str.charAt(i); 2211 2212 for (int j = 0; j < searchChars.length(); j++) { 2213 if (searchChars.charAt(j) == ch) { 2214 return i; 2215 } 2216 } 2217 } 2218 2219 return -1; 2220 } 2221 2222 /** 2223 * 在字符串中查找指定字符串集合中的字符串,并返回第一个匹配的起始索引。 如果字符串为<code>null</code>,则返回<code>-1</code>。 2224 * 如果字符串集合为<code>null</code>或空,也返回<code>-1</code>。 2225 * 如果字符串集合包括<code>""</code>,并且字符串不为<code>null</code>,则返回<code>str.length()</code> 2226 * <pre> 2227 * StringUtil.indexOfAny(null, *) = -1 2228 * StringUtil.indexOfAny(*, null) = -1 2229 * StringUtil.indexOfAny(*, []) = -1 2230 * StringUtil.indexOfAny("zzabyycdxx", ["ab","cd"]) = 2 2231 * StringUtil.indexOfAny("zzabyycdxx", ["cd","ab"]) = 2 2232 * StringUtil.indexOfAny("zzabyycdxx", ["mn","op"]) = -1 2233 * StringUtil.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1 2234 * StringUtil.indexOfAny("zzabyycdxx", [""]) = 0 2235 * StringUtil.indexOfAny("", [""]) = 0 2236 * StringUtil.indexOfAny("", ["a"]) = -1 2237 * </pre> 2238 * 2239 * @param str 要扫描的字符串 2240 * @param searchStrs 要搜索的字符串集合 2241 * 2242 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2243 */ 2244 public static int indexOfAny(String str, String[] searchStrs) { 2245 if ((str == null) || (searchStrs == null)) { 2246 return -1; 2247 } 2248 2249 int sz = searchStrs.length; 2250 2251 // String's can't have a MAX_VALUEth index. 2252 int ret = Integer.MAX_VALUE; 2253 2254 int tmp = 0; 2255 2256 for (int i = 0; i < sz; i++) { 2257 String search = searchStrs[i]; 2258 2259 if (search == null) { 2260 continue; 2261 } 2262 2263 tmp = str.indexOf(search); 2264 2265 if (tmp == -1) { 2266 continue; 2267 } 2268 2269 if (tmp < ret) { 2270 ret = tmp; 2271 } 2272 } 2273 2274 return (ret == Integer.MAX_VALUE) ? (-1) : ret; 2275 } 2276 2277 /** 2278 * 在字符串中查找不在指定字符集合中的字符,并返回第一个匹配的起始索引。 如果字符串为<code>null</code>,则返回<code>-1</code>。 2279 * 如果字符集合为<code>null</code>或空,也返回<code>-1</code>。 2280 * <pre> 2281 * StringUtil.indexOfAnyBut(null, *) = -1 2282 * StringUtil.indexOfAnyBut("", *) = -1 2283 * StringUtil.indexOfAnyBut(*, null) = -1 2284 * StringUtil.indexOfAnyBut(*, []) = -1 2285 * StringUtil.indexOfAnyBut("zzabyycdxx",'za') = 3 2286 * StringUtil.indexOfAnyBut("zzabyycdxx", 'by') = 0 2287 * StringUtil.indexOfAnyBut("aba", 'ab') = -1 2288 * </pre> 2289 * 2290 * @param str 要扫描的字符串 2291 * @param searchChars 要搜索的字符集合 2292 * 2293 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2294 */ 2295 public static int indexOfAnyBut(String str, char[] searchChars) { 2296 if ((str == null) || (str.length() == 0) || (searchChars == null) 2297 || (searchChars.length == 0)) { 2298 return -1; 2299 } 2300 2301 outer: for (int i = 0; i < str.length(); i++) { 2302 char ch = str.charAt(i); 2303 2304 for (int j = 0; j < searchChars.length; j++) { 2305 if (searchChars[j] == ch) { 2306 continue outer; 2307 } 2308 } 2309 2310 return i; 2311 } 2312 2313 return -1; 2314 } 2315 2316 /** 2317 * 在字符串中查找不在指定字符集合中的字符,并返回第一个匹配的起始索引。 如果字符串为<code>null</code>,则返回<code>-1</code>。 2318 * 如果字符集合为<code>null</code>或空,也返回<code>-1</code>。 2319 * <pre> 2320 * StringUtil.indexOfAnyBut(null, *) = -1 2321 * StringUtil.indexOfAnyBut("", *) = -1 2322 * StringUtil.indexOfAnyBut(*, null) = -1 2323 * StringUtil.indexOfAnyBut(*, "") = -1 2324 * StringUtil.indexOfAnyBut("zzabyycdxx", "za") = 3 2325 * StringUtil.indexOfAnyBut("zzabyycdxx", "by") = 0 2326 * StringUtil.indexOfAnyBut("aba","ab") = -1 2327 * </pre> 2328 * 2329 * @param str 要扫描的字符串 2330 * @param searchChars 要搜索的字符集合 2331 * 2332 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2333 */ 2334 public static int indexOfAnyBut(String str, String searchChars) { 2335 if ((str == null) || (str.length() == 0) || (searchChars == null) 2336 || (searchChars.length() == 0)) { 2337 return -1; 2338 } 2339 2340 for (int i = 0; i < str.length(); i++) { 2341 if (searchChars.indexOf(str.charAt(i)) < 0) { 2342 return i; 2343 } 2344 } 2345 2346 return -1; 2347 } 2348 2349 /** 2350 * 从字符串尾部开始查找指定字符,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2351 * <pre> 2352 * StringUtil.lastIndexOf(null, *) = -1 2353 * StringUtil.lastIndexOf("", *) = -1 2354 * StringUtil.lastIndexOf("aabaabaa", 'a') = 7 2355 * StringUtil.lastIndexOf("aabaabaa", 'b') = 5 2356 * </pre> 2357 * 2358 * @param str 要扫描的字符串 2359 * @param searchChar 要查找的字符 2360 * 2361 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2362 */ 2363 public static int lastIndexOf(String str, char searchChar) { 2364 if ((str == null) || (str.length() == 0)) { 2365 return -1; 2366 } 2367 2368 return str.lastIndexOf(searchChar); 2369 } 2370 2371 /** 2372 * 从字符串尾部开始查找指定字符,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2373 * <pre> 2374 * StringUtil.lastIndexOf(null, *, *) = -1 2375 * StringUtil.lastIndexOf("", *, *) = -1 2376 * StringUtil.lastIndexOf("aabaabaa", 'b', 8) = 5 2377 * StringUtil.lastIndexOf("aabaabaa", 'b', 4) = 2 2378 * StringUtil.lastIndexOf("aabaabaa", 'b', 0) = -1 2379 * StringUtil.lastIndexOf("aabaabaa", 'b', 9) = 5 2380 * StringUtil.lastIndexOf("aabaabaa", 'b', -1) = -1 2381 * StringUtil.lastIndexOf("aabaabaa", 'a', 0) = 0 2382 * </pre> 2383 * 2384 * @param str 要扫描的字符串 2385 * @param searchChar 要查找的字符 2386 * @param startPos 从指定索引开始向前搜索 2387 * 2388 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2389 */ 2390 public static int lastIndexOf(String str, char searchChar, int startPos) { 2391 if ((str == null) || (str.length() == 0)) { 2392 return -1; 2393 } 2394 2395 return str.lastIndexOf(searchChar, startPos); 2396 } 2397 2398 /** 2399 * 从字符串尾部开始查找指定字符串,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2400 * <pre> 2401 * StringUtil.lastIndexOf(null, *) = -1 2402 * StringUtil.lastIndexOf("", *) = -1 2403 * StringUtil.lastIndexOf("aabaabaa", 'a') = 7 2404 * StringUtil.lastIndexOf("aabaabaa", 'b') = 5 2405 * </pre> 2406 * 2407 * @param str 要扫描的字符串 2408 * @param searchStr 要查找的字符串 2409 * 2410 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2411 */ 2412 public static int lastIndexOf(String str, String searchStr) { 2413 if ((str == null) || (searchStr == null)) { 2414 return -1; 2415 } 2416 2417 return str.lastIndexOf(searchStr); 2418 } 2419 2420 /** 2421 * 从字符串尾部开始查找指定字符串,并返回第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code>。 2422 * <pre> 2423 * StringUtil.lastIndexOf(null, *, *) = -1 2424 * StringUtil.lastIndexOf(*, null, *) = -1 2425 * StringUtil.lastIndexOf("aabaabaa", "a", 8) = 7 2426 * StringUtil.lastIndexOf("aabaabaa", "b", 8) = 5 2427 * StringUtil.lastIndexOf("aabaabaa", "ab", 8) = 4 2428 * StringUtil.lastIndexOf("aabaabaa", "b", 9) = 5 2429 * StringUtil.lastIndexOf("aabaabaa", "b", -1) = -1 2430 * StringUtil.lastIndexOf("aabaabaa", "a", 0) = 0 2431 * StringUtil.lastIndexOf("aabaabaa", "b", 0) = -1 2432 * </pre> 2433 * 2434 * @param str 要扫描的字符串 2435 * @param searchStr 要查找的字符串 2436 * @param startPos 从指定索引开始向前搜索 2437 * 2438 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2439 */ 2440 public static int lastIndexOf(String str, String searchStr, int startPos) { 2441 if ((str == null) || (searchStr == null)) { 2442 return -1; 2443 } 2444 2445 return str.lastIndexOf(searchStr, startPos); 2446 } 2447 2448 /** 2449 * 从字符串尾部开始查找指定字符串集合中的字符串,并返回第一个匹配的起始索引。 如果字符串为<code>null</code>,则返回<code>-1</code>。 2450 * 如果字符串集合为<code>null</code>或空,也返回<code>-1</code>。 2451 * 如果字符串集合包括<code>""</code>,并且字符串不为<code>null</code>,则返回<code>str.length()</code> 2452 * <pre> 2453 * StringUtil.lastIndexOfAny(null, *) = -1 2454 * StringUtil.lastIndexOfAny(*, null) = -1 2455 * StringUtil.lastIndexOfAny(*, []) = -1 2456 * StringUtil.lastIndexOfAny(*, [null]) = -1 2457 * StringUtil.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6 2458 * StringUtil.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6 2459 * StringUtil.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1 2460 * StringUtil.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1 2461 * StringUtil.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10 2462 * </pre> 2463 * 2464 * @param str 要扫描的字符串 2465 * @param searchStrs 要搜索的字符串集合 2466 * 2467 * @return 第一个匹配的索引值。如果字符串为<code>null</code>或未找到,则返回<code>-1</code> 2468 */ 2469 public static int lastIndexOfAny(String str, String[] searchStrs) { 2470 if ((str == null) || (searchStrs == null)) { 2471 return -1; 2472 } 2473 2474 int searchStrsLength = searchStrs.length; 2475 int index = -1; 2476 int tmp = 0; 2477 2478 for (int i = 0; i < searchStrsLength; i++) { 2479 String search = searchStrs[i]; 2480 2481 if (search == null) { 2482 continue; 2483 } 2484 2485 tmp = str.lastIndexOf(search); 2486 2487 if (tmp > index) { 2488 index = tmp; 2489 } 2490 } 2491 2492 return index; 2493 } 2494 2495 /** 2496 * 检查字符串中是否包含指定的字符。如果字符串为<code>null</code>,将返回<code>false</code>。 2497 * <pre> 2498 * StringUtil.contains(null, *) = false 2499 * StringUtil.contains("", *) = false 2500 * StringUtil.contains("abc", 'a') = true 2501 * StringUtil.contains("abc", 'z') = false 2502 * </pre> 2503 * 2504 * @param str 要扫描的字符串 2505 * @param searchChar 要查找的字符 2506 * 2507 * @return 如果找到,则返回<code>true</code> 2508 */ 2509 public static boolean contains(String str, char searchChar) { 2510 if ((str == null) || (str.length() == 0)) { 2511 return false; 2512 } 2513 2514 return str.indexOf(searchChar) >= 0; 2515 } 2516 2517 /** 2518 * 检查字符串中是否包含指定的字符串。如果字符串为<code>null</code>,将返回<code>false</code>。 2519 * <pre> 2520 * StringUtil.contains(null, *) = false 2521 * StringUtil.contains(*, null) = false 2522 * StringUtil.contains("", "") = true 2523 * StringUtil.contains("abc", "") = true 2524 * StringUtil.contains("abc", "a") = true 2525 * StringUtil.contains("abc", "z") = false 2526 * </pre> 2527 * 2528 * @param str 要扫描的字符串 2529 * @param searchStr 要查找的字符串 2530 * 2531 * @return 如果找到,则返回<code>true</code> 2532 */ 2533 public static boolean contains(String str, String searchStr) { 2534 if ((str == null) || (searchStr == null)) { 2535 return false; 2536 } 2537 2538 return str.indexOf(searchStr) >= 0; 2539 } 2540 2541 /** 2542 * 检查字符串是是否只包含指定字符集合中的字符。 2543 * 2544 * <p> 2545 * 如果字符串为<code>null</code>,则返回<code>false</code>。 2546 * 如果字符集合为<code>null</code>则返回<code>false</code>。 但是空字符串永远返回<code>true</code>. 2547 * </p> 2548 * <pre> 2549 * StringUtil.containsOnly(null, *) = false 2550 * StringUtil.containsOnly(*, null) = false 2551 * StringUtil.containsOnly("", *) = true 2552 * StringUtil.containsOnly("ab", '') = false 2553 * StringUtil.containsOnly("abab", 'abc') = true 2554 * StringUtil.containsOnly("ab1", 'abc') = false 2555 * StringUtil.containsOnly("abz", 'abc') = false 2556 * </pre> 2557 * 2558 * @param str 要扫描的字符串 2559 * @param valid 要查找的字符串 2560 * 2561 * @return 如果找到,则返回<code>true</code> 2562 */ 2563 public static boolean containsOnly(String str, char[] valid) { 2564 if ((valid == null) || (str == null)) { 2565 return false; 2566 } 2567 2568 if (str.length() == 0) { 2569 return true; 2570 } 2571 2572 if (valid.length == 0) { 2573 return false; 2574 } 2575 2576 return indexOfAnyBut(str, valid) == -1; 2577 } 2578 2579 /** 2580 * 检查字符串是是否只包含指定字符集合中的字符。 2581 * 2582 * <p> 2583 * 如果字符串为<code>null</code>,则返回<code>false</code>。 2584 * 如果字符集合为<code>null</code>则返回<code>false</code>。 但是空字符串永远返回<code>true</code>. 2585 * </p> 2586 * <pre> 2587 * StringUtil.containsOnly(null, *) = false 2588 * StringUtil.containsOnly(*, null) = false 2589 * StringUtil.containsOnly("", *) = true 2590 * StringUtil.containsOnly("ab", "") = false 2591 * StringUtil.containsOnly("abab", "abc") = true 2592 * StringUtil.containsOnly("ab1", "abc") = false 2593 * StringUtil.containsOnly("abz", "abc") = false 2594 * </pre> 2595 * 2596 * @param str 要扫描的字符串 2597 * @param valid 要查找的字符串 2598 * 2599 * @return 如果找到,则返回<code>true</code> 2600 */ 2601 public static boolean containsOnly(String str, String valid) { 2602 if ((str == null) || (valid == null)) { 2603 return false; 2604 } 2605 2606 return containsOnly(str, valid.toCharArray()); 2607 } 2608 2609 /** 2610 * 检查字符串是是否不包含指定字符集合中的字符。 2611 * 2612 * <p> 2613 * 如果字符串为<code>null</code>,则返回<code>false</code>。 如果字符集合为<code>null</code>则返回<code>true</code>。 2614 * 但是空字符串永远返回<code>true</code>. 2615 * </p> 2616 * <pre> 2617 * StringUtil.containsNone(null, *) = true 2618 * StringUtil.containsNone(*, null) = true 2619 * StringUtil.containsNone("", *) = true 2620 * StringUtil.containsNone("ab", '') = true 2621 * StringUtil.containsNone("abab", 'xyz') = true 2622 * StringUtil.containsNone("ab1", 'xyz') = true 2623 * StringUtil.containsNone("abz", 'xyz') = false 2624 * </pre> 2625 * 2626 * @param str 要扫描的字符串 2627 * @param invalid 要查找的字符串 2628 * 2629 * @return 如果找到,则返回<code>true</code> 2630 */ 2631 public static boolean containsNone(String str, char[] invalid) { 2632 if ((str == null) || (invalid == null)) { 2633 return true; 2634 } 2635 2636 int strSize = str.length(); 2637 int validSize = invalid.length; 2638 2639 for (int i = 0; i < strSize; i++) { 2640 char ch = str.charAt(i); 2641 2642 for (int j = 0; j < validSize; j++) { 2643 if (invalid[j] == ch) { 2644 return false; 2645 } 2646 } 2647 } 2648 2649 return true; 2650 } 2651 2652 /** 2653 * 检查字符串是是否不包含指定字符集合中的字符。 2654 * 2655 * <p> 2656 * 如果字符串为<code>null</code>,则返回<code>false</code>。 如果字符集合为<code>null</code>则返回<code>true</code>。 2657 * 但是空字符串永远返回<code>true</code>. 2658 * </p> 2659 * <pre> 2660 * StringUtil.containsNone(null, *) = true 2661 * StringUtil.containsNone(*, null) = true 2662 * StringUtil.containsNone("", *) = true 2663 * StringUtil.containsNone("ab", "") = true 2664 * StringUtil.containsNone("abab", "xyz") = true 2665 * StringUtil.containsNone("ab1", "xyz") = true 2666 * StringUtil.containsNone("abz", "xyz") = false 2667 * </pre> 2668 * 2669 * @param str 要扫描的字符串 2670 * @param invalidChars 要查找的字符串 2671 * 2672 * @return 如果找到,则返回<code>true</code> 2673 */ 2674 public static boolean containsNone(String str, String invalidChars) { 2675 if ((str == null) || (invalidChars == null)) { 2676 return true; 2677 } 2678 2679 return containsNone(str, invalidChars.toCharArray()); 2680 } 2681 2682 /** 2683 * 取得指定子串在字符串中出现的次数。 2684 * 2685 * <p> 2686 * 如果字符串为<code>null</code>或空,则返回<code>0</code>。 2687 * <pre> 2688 * StringUtil.countMatches(null, *) = 0 2689 * StringUtil.countMatches("", *) = 0 2690 * StringUtil.countMatches("abba", null) = 0 2691 * StringUtil.countMatches("abba", "") = 0 2692 * StringUtil.countMatches("abba", "a") = 2 2693 * StringUtil.countMatches("abba", "ab") = 1 2694 * StringUtil.countMatches("abba", "xxx") = 0 2695 * </pre> 2696 * </p> 2697 * 2698 * @param str 要扫描的字符串 2699 * @param subStr 子字符串 2700 * 2701 * @return 子串在字符串中出现的次数,如果字符串为<code>null</code>或空,则返回<code>0</code> 2702 */ 2703 public static int countMatches(String str, String subStr) { 2704 if ((str == null) || (str.length() == 0) || (subStr == null) || (subStr.length() == 0)) { 2705 return 0; 2706 } 2707 2708 int count = 0; 2709 int index = 0; 2710 2711 while ((index = str.indexOf(subStr, index)) != -1) { 2712 count++; 2713 index += subStr.length(); 2714 } 2715 2716 return count; 2717 } 2718 2719 /* ============================================================================ */ 2720 /* 取子串函数。 */ 2721 /* ============================================================================ */ 2722 2723 /** 2724 * 取指定字符串的子串。 2725 * 2726 * <p> 2727 * 负的索引代表从尾部开始计算。如果字符串为<code>null</code>,则返回<code>null</code>。 2728 * <pre> 2729 * StringUtil.substring(null, *) = null 2730 * StringUtil.substring("", *) = "" 2731 * StringUtil.substring("abc", 0) = "abc" 2732 * StringUtil.substring("abc", 2) = "c" 2733 * StringUtil.substring("abc", 4) = "" 2734 * StringUtil.substring("abc", -2) = "bc" 2735 * StringUtil.substring("abc", -4) = "abc" 2736 * </pre> 2737 * </p> 2738 * 2739 * @param str 字符串 2740 * @param start 起始索引,如果为负数,表示从尾部查找 2741 * 2742 * @return 子串,如果原始串为<code>null</code>,则返回<code>null</code> 2743 */ 2744 public static String substring(String str, int start) { 2745 if (str == null) { 2746 return null; 2747 } 2748 2749 if (start < 0) { 2750 start = str.length() + start; 2751 } 2752 2753 if (start < 0) { 2754 start = 0; 2755 } 2756 2757 if (start > str.length()) { 2758 return EMPTY_STRING; 2759 } 2760 2761 return str.substring(start); 2762 } 2763 2764 /** 2765 * 取指定字符串的子串。 2766 * 2767 * <p> 2768 * 负的索引代表从尾部开始计算。如果字符串为<code>null</code>,则返回<code>null</code>。 2769 * <pre> 2770 * StringUtil.substring(null, *, *) = null 2771 * StringUtil.substring("", * , *) = ""; 2772 * StringUtil.substring("abc", 0, 2) = "ab" 2773 * StringUtil.substring("abc", 2, 0) = "" 2774 * StringUtil.substring("abc", 2, 4) = "c" 2775 * StringUtil.substring("abc", 4, 6) = "" 2776 * StringUtil.substring("abc", 2, 2) = "" 2777 * StringUtil.substring("abc", -2, -1) = "b" 2778 * StringUtil.substring("abc", -4, 2) = "ab" 2779 * </pre> 2780 * </p> 2781 * 2782 * @param str 字符串 2783 * @param start 起始索引,如果为负数,表示从尾部计算 2784 * @param end 结束索引(不含),如果为负数,表示从尾部计算 2785 * 2786 * @return 子串,如果原始串为<code>null</code>,则返回<code>null</code> 2787 */ 2788 public static String substring(String str, int start, int end) { 2789 if (str == null) { 2790 return null; 2791 } 2792 2793 if (end < 0) { 2794 end = str.length() + end; 2795 } 2796 2797 if (start < 0) { 2798 start = str.length() + start; 2799 } 2800 2801 if (end > str.length()) { 2802 end = str.length(); 2803 } 2804 2805 if (start > end) { 2806 return EMPTY_STRING; 2807 } 2808 2809 if (start < 0) { 2810 start = 0; 2811 } 2812 2813 if (end < 0) { 2814 end = 0; 2815 } 2816 2817 return str.substring(start, end); 2818 } 2819 2820 /** 2821 * 取得长度为指定字符数的最左边的子串。 2822 * <pre> 2823 * StringUtil.left(null, *) = null 2824 * StringUtil.left(*, -ve) = "" 2825 * StringUtil.left("", *) = "" 2826 * StringUtil.left("abc", 0) = "" 2827 * StringUtil.left("abc", 2) = "ab" 2828 * StringUtil.left("abc", 4) = "abc" 2829 * </pre> 2830 * 2831 * @param str 字符串 2832 * @param len 最左子串的长度 2833 * 2834 * @return 子串,如果原始字串为<code>null</code>,则返回<code>null</code> 2835 */ 2836 public static String left(String str, int len) { 2837 if (str == null) { 2838 return null; 2839 } 2840 2841 if (len < 0) { 2842 return EMPTY_STRING; 2843 } 2844 2845 if (str.length() <= len) { 2846 return str; 2847 } else { 2848 return str.substring(0, len); 2849 } 2850 } 2851 2852 /** 2853 * 取得长度为指定字符数的最右边的子串。 2854 * <pre> 2855 * StringUtil.right(null, *) = null 2856 * StringUtil.right(*, -ve) = "" 2857 * StringUtil.right("", *) = "" 2858 * StringUtil.right("abc", 0) = "" 2859 * StringUtil.right("abc", 2) = "bc" 2860 * StringUtil.right("abc", 4) = "abc" 2861 * </pre> 2862 * 2863 * @param str 字符串 2864 * @param len 最右子串的长度 2865 * 2866 * @return 子串,如果原始字串为<code>null</code>,则返回<code>null</code> 2867 */ 2868 public static String right(String str, int len) { 2869 if (str == null) { 2870 return null; 2871 } 2872 2873 if (len < 0) { 2874 return EMPTY_STRING; 2875 } 2876 2877 if (str.length() <= len) { 2878 return str; 2879 } else { 2880 return str.substring(str.length() - len); 2881 } 2882 } 2883 2884 /** 2885 * 取得从指定索引开始计算的、长度为指定字符数的子串。 2886 * <pre> 2887 * StringUtil.mid(null, *, *) = null 2888 * StringUtil.mid(*, *, -ve) = "" 2889 * StringUtil.mid("", 0, *) = "" 2890 * StringUtil.mid("abc", 0, 2) = "ab" 2891 * StringUtil.mid("abc", 0, 4) = "abc" 2892 * StringUtil.mid("abc", 2, 4) = "c" 2893 * StringUtil.mid("abc", 4, 2) = "" 2894 * StringUtil.mid("abc", -2, 2) = "ab" 2895 * </pre> 2896 * 2897 * @param str 字符串 2898 * @param pos 起始索引,如果为负数,则看作<code>0</code> 2899 * @param len 子串的长度,如果为负数,则看作长度为<code>0</code> 2900 * 2901 * @return 子串,如果原始字串为<code>null</code>,则返回<code>null</code> 2902 */ 2903 public static String mid(String str, int pos, int len) { 2904 if (str == null) { 2905 return null; 2906 } 2907 2908 if ((len < 0) || (pos > str.length())) { 2909 return EMPTY_STRING; 2910 } 2911 2912 if (pos < 0) { 2913 pos = 0; 2914 } 2915 2916 if (str.length() <= (pos + len)) { 2917 return str.substring(pos); 2918 } else { 2919 return str.substring(pos, pos + len); 2920 } 2921 } 2922 2923 /* ============================================================================ */ 2924 /* 搜索并取子串函数。 */ 2925 /* ============================================================================ */ 2926 2927 /** 2928 * 取得第一个出现的分隔子串之前的子串。 2929 * 2930 * <p> 2931 * 如果字符串为<code>null</code>,则返回<code>null</code>。 如果分隔子串为<code>null</code>或未找到该子串,则返回原字符串。 2932 * <pre> 2933 * StringUtil.substringBefore(null, *) = null 2934 * StringUtil.substringBefore("", *) = "" 2935 * StringUtil.substringBefore("abc", "a") = "" 2936 * StringUtil.substringBefore("abcba", "b") = "a" 2937 * StringUtil.substringBefore("abc", "c") = "ab" 2938 * StringUtil.substringBefore("abc", "d") = "abc" 2939 * StringUtil.substringBefore("abc", "") = "" 2940 * StringUtil.substringBefore("abc", null) = "abc" 2941 * </pre> 2942 * </p> 2943 * 2944 * @param str 字符串 2945 * @param separator 要搜索的分隔子串 2946 * 2947 * @return 子串,如果原始串为<code>null</code>,则返回<code>null</code> 2948 */ 2949 public static String substringBefore(String str, String separator) { 2950 if ((str == null) || (separator == null) || (str.length() == 0)) { 2951 return str; 2952 } 2953 2954 if (separator.length() == 0) { 2955 return EMPTY_STRING; 2956 } 2957 2958 int pos = str.indexOf(separator); 2959 2960 if (pos == -1) { 2961 return str; 2962 } 2963 2964 return str.substring(0, pos); 2965 } 2966 2967 /** 2968 * 取得第一个出现的分隔子串之后的子串。 2969 * 2970 * <p> 2971 * 如果字符串为<code>null</code>,则返回<code>null</code>。 如果分隔子串为<code>null</code>或未找到该子串,则返回原字符串。 2972 * <pre> 2973 * StringUtil.substringAfter(null, *) = null 2974 * StringUtil.substringAfter("", *) = "" 2975 * StringUtil.substringAfter(*, null) = "" 2976 * StringUtil.substringAfter("abc", "a") = "bc" 2977 * StringUtil.substringAfter("abcba", "b") = "cba" 2978 * StringUtil.substringAfter("abc", "c") = "" 2979 * StringUtil.substringAfter("abc", "d") = "" 2980 * StringUtil.substringAfter("abc", "") = "abc" 2981 * </pre> 2982 * </p> 2983 * 2984 * @param str 字符串 2985 * @param separator 要搜索的分隔子串 2986 * 2987 * @return 子串,如果原始串为<code>null</code>,则返回<code>null</code> 2988 */ 2989 public static String substringAfter(String str, String separator) { 2990 if ((str == null) || (str.length() == 0)) { 2991 return str; 2992 } 2993 2994 if (separator == null) { 2995 return EMPTY_STRING; 2996 } 2997 2998 int pos = str.indexOf(separator); 2999 3000 if (pos == -1) { 3001 return EMPTY_STRING; 3002 } 3003 3004 return str.substring(pos + separator.length()); 3005 } 3006 3007 /** 3008 * 取得最后一个的分隔子串之前的子串。 3009 * 3010 * <p> 3011 * 如果字符串为<code>null</code>,则返回<code>null</code>。 如果分隔子串为<code>null</code>或未找到该子串,则返回原字符串。 3012 * <pre> 3013 * StringUtil.substringBeforeLast(null, *) = null 3014 * StringUtil.substringBeforeLast("", *) = "" 3015 * StringUtil.substringBeforeLast("abcba", "b") = "abc" 3016 * StringUtil.substringBeforeLast("abc", "c") = "ab" 3017 * StringUtil.substringBeforeLast("a", "a") = "" 3018 * StringUtil.substringBeforeLast("a", "z") = "a" 3019 * StringUtil.substringBeforeLast("a", null) = "a" 3020 * StringUtil.substringBeforeLast("a", "") = "a" 3021 * </pre> 3022 * </p> 3023 * 3024 * @param str 字符串 3025 * @param separator 要搜索的分隔子串 3026 * 3027 * @return 子串,如果原始串为<code>null</code>,则返回<code>null</code> 3028 */ 3029 public static String substringBeforeLast(String str, String separator) { 3030 if ((str == null) || (separator == null) || (str.length() == 0) 3031 || (separator.length() == 0)) { 3032 return str; 3033 } 3034 3035 int pos = str.lastIndexOf(separator); 3036 3037 if (pos == -1) { 3038 return str; 3039 } 3040 3041 return str.substring(0, pos); 3042 } 3043 3044 /** 3045 * 取得最后一个的分隔子串之后的子串。 3046 * 3047 * <p> 3048 * 如果字符串为<code>null</code>,则返回<code>null</code>。 如果分隔子串为<code>null</code>或未找到该子串,则返回原字符串。 3049 * <pre> 3050 * StringUtil.substringAfterLast(null, *) = null 3051 * StringUtil.substringAfterLast("", *) = "" 3052 * StringUtil.substringAfterLast(*, "") = "" 3053 * StringUtil.substringAfterLast(*, null) = "" 3054 * StringUtil.substringAfterLast("abc", "a") = "bc" 3055 * StringUtil.substringAfterLast("abcba", "b") = "a" 3056 * StringUtil.substringAfterLast("abc", "c") = "" 3057 * StringUtil.substringAfterLast("a", "a") = "" 3058 * StringUtil.substringAfterLast("a", "z") = "" 3059 * </pre> 3060 * </p> 3061 * 3062 * @param str 字符串 3063 * @param separator 要搜索的分隔子串 3064 * 3065 * @return 子串,如果原始串为<code>null</code>,则返回<code>null</code> 3066 */ 3067 public static String substringAfterLast(String str, String separator) { 3068 if ((str == null) || (str.length() == 0)) { 3069 return str; 3070 } 3071 3072 if ((separator == null) || (separator.length() == 0)) { 3073 return EMPTY_STRING; 3074 } 3075 3076 int pos = str.lastIndexOf(separator); 3077 3078 if ((pos == -1) || (pos == (str.length() - separator.length()))) { 3079 return EMPTY_STRING; 3080 } 3081 3082 return str.substring(pos + separator.length()); 3083 } 3084 3085 /** 3086 * 取得指定分隔符的前两次出现之间的子串。 3087 * 3088 * <p> 3089 * 如果字符串为<code>null</code>,则返回<code>null</code>。 如果分隔子串为<code>null</code>,则返回<code>null</code>。 3090 * <pre> 3091 * StringUtil.substringBetween(null, *) = null 3092 * StringUtil.substringBetween("", "") = "" 3093 * StringUtil.substringBetween("", "tag") = null 3094 * StringUtil.substringBetween("tagabctag", null) = null 3095 * StringUtil.substringBetween("tagabctag", "") = "" 3096 * StringUtil.substringBetween("tagabctag", "tag") = "abc" 3097 * </pre> 3098 * </p> 3099 * 3100 * @param str 字符串 3101 * @param tag 要搜索的分隔子串 3102 * 3103 * @return 子串,如果原始串为<code>null</code>或未找到分隔子串,则返回<code>null</code> 3104 */ 3105 public static String substringBetween(String str, String tag) { 3106 return substringBetween(str, tag, tag, 0); 3107 } 3108 3109 /** 3110 * 取得两个分隔符之间的子串。 3111 * 3112 * <p> 3113 * 如果字符串为<code>null</code>,则返回<code>null</code>。 如果分隔子串为<code>null</code>,则返回<code>null</code>。 3114 * <pre> 3115 * StringUtil.substringBetween(null, *, *) = null 3116 * StringUtil.substringBetween("", "", "") = "" 3117 * StringUtil.substringBetween("", "", "tag") = null 3118 * StringUtil.substringBetween("", "tag", "tag") = null 3119 * StringUtil.substringBetween("yabcz", null, null) = null 3120 * StringUtil.substringBetween("yabcz", "", "") = "" 3121 * StringUtil.substringBetween("yabcz", "y", "z") = "abc" 3122 * StringUtil.substringBetween("yabczyabcz", "y", "z") = "abc" 3123 * </pre> 3124 * </p> 3125 * 3126 * @param str 字符串 3127 * @param open 要搜索的分隔子串1 3128 * @param close 要搜索的分隔子串2 3129 * 3130 * @return 子串,如果原始串为<code>null</code>或未找到分隔子串,则返回<code>null</code> 3131 */ 3132 public static String substringBetween(String str, String open, String close) { 3133 return substringBetween(str, open, close, 0); 3134 } 3135 3136 /** 3137 * 取得两个分隔符之间的子串。 3138 * 3139 * <p> 3140 * 如果字符串为<code>null</code>,则返回<code>null</code>。 如果分隔子串为<code>null</code>,则返回<code>null</code>。 3141 * <pre> 3142 * StringUtil.substringBetween(null, *, *) = null 3143 * StringUtil.substringBetween("", "", "") = "" 3144 * StringUtil.substringBetween("", "", "tag") = null 3145 * StringUtil.substringBetween("", "tag", "tag") = null 3146 * StringUtil.substringBetween("yabcz", null, null) = null 3147 * StringUtil.substringBetween("yabcz", "", "") = "" 3148 * StringUtil.substringBetween("yabcz", "y", "z") = "abc" 3149 * StringUtil.substringBetween("yabczyabcz", "y", "z") = "abc" 3150 * </pre> 3151 * </p> 3152 * 3153 * @param str 字符串 3154 * @param open 要搜索的分隔子串1 3155 * @param close 要搜索的分隔子串2 3156 * @param fromIndex 从指定index处搜索 3157 * 3158 * @return 子串,如果原始串为<code>null</code>或未找到分隔子串,则返回<code>null</code> 3159 */ 3160 public static String substringBetween(String str, String open, String close, int fromIndex) { 3161 if ((str == null) || (open == null) || (close == null)) { 3162 return null; 3163 } 3164 3165 int start = str.indexOf(open, fromIndex); 3166 3167 if (start != -1) { 3168 int end = str.indexOf(close, start + open.length()); 3169 3170 if (end != -1) { 3171 return str.substring(start + open.length(), end); 3172 } 3173 } 3174 3175 return null; 3176 } 3177 3178 /* ============================================================================ */ 3179 /* 删除字符。 */ 3180 /* ============================================================================ */ 3181 3182 /** 3183 * 删除所有在<code>Character.isWhitespace(char)</code>中所定义的空白。 3184 * <pre> 3185 * StringUtil.deleteWhitespace(null) = null 3186 * StringUtil.deleteWhitespace("") = "" 3187 * StringUtil.deleteWhitespace("abc") = "abc" 3188 * StringUtil.deleteWhitespace(" ab c ") = "abc" 3189 * </pre> 3190 * 3191 * @param str 要处理的字符串 3192 * 3193 * @return 去空白后的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3194 */ 3195 public static String deleteWhitespace(String str) { 3196 if (str == null) { 3197 return null; 3198 } 3199 3200 int sz = str.length(); 3201 StringBuffer buffer = new StringBuffer(sz); 3202 3203 for (int i = 0; i < sz; i++) { 3204 if (!Character.isWhitespace(str.charAt(i))) { 3205 buffer.append(str.charAt(i)); 3206 } 3207 } 3208 3209 return buffer.toString(); 3210 } 3211 3212 /* ============================================================================ */ 3213 /* 替换子串。 */ 3214 /* ============================================================================ */ 3215 3216 /** 3217 * 替换指定的子串,只替换第一个出现的子串。 3218 * 3219 * <p> 3220 * 如果字符串为<code>null</code>则返回<code>null</code>,如果指定子串为<code>null</code>,则返回原字符串。 3221 * <pre> 3222 * StringUtil.replaceOnce(null, *, *) = null 3223 * StringUtil.replaceOnce("", *, *) = "" 3224 * StringUtil.replaceOnce("aba", null, null) = "aba" 3225 * StringUtil.replaceOnce("aba", null, null) = "aba" 3226 * StringUtil.replaceOnce("aba", "a", null) = "aba" 3227 * StringUtil.replaceOnce("aba", "a", "") = "ba" 3228 * StringUtil.replaceOnce("aba", "a", "z") = "zba" 3229 * </pre> 3230 * </p> 3231 * 3232 * @param text 要扫描的字符串 3233 * @param repl 要搜索的子串 3234 * @param with 替换字符串 3235 * 3236 * @return 被替换后的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3237 */ 3238 public static String replaceOnce(String text, String repl, String with) { 3239 return replace(text, repl, with, 1); 3240 } 3241 3242 /** 3243 * 替换指定的子串,替换所有出现的子串。 3244 * 3245 * <p> 3246 * 如果字符串为<code>null</code>则返回<code>null</code>,如果指定子串为<code>null</code>,则返回原字符串。 3247 * <pre> 3248 * StringUtil.replace(null, *, *) = null 3249 * StringUtil.replace("", *, *) = "" 3250 * StringUtil.replace("aba", null, null) = "aba" 3251 * StringUtil.replace("aba", null, null) = "aba" 3252 * StringUtil.replace("aba", "a", null) = "aba" 3253 * StringUtil.replace("aba", "a", "") = "b" 3254 * StringUtil.replace("aba", "a", "z") = "zbz" 3255 * </pre> 3256 * </p> 3257 * 3258 * @param text 要扫描的字符串 3259 * @param repl 要搜索的子串 3260 * @param with 替换字符串 3261 * 3262 * @return 被替换后的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3263 */ 3264 public static String replace(String text, String repl, String with) { 3265 return replace(text, repl, with, -1); 3266 } 3267 3268 /** 3269 * 替换指定的子串,替换指定的次数。 3270 * 3271 * <p> 3272 * 如果字符串为<code>null</code>则返回<code>null</code>,如果指定子串为<code>null</code>,则返回原字符串。 3273 * <pre> 3274 * StringUtil.replace(null, *, *, *) = null 3275 * StringUtil.replace("", *, *, *) = "" 3276 * StringUtil.replace("abaa", null, null, 1) = "abaa" 3277 * StringUtil.replace("abaa", null, null, 1) = "abaa" 3278 * StringUtil.replace("abaa", "a", null, 1) = "abaa" 3279 * StringUtil.replace("abaa", "a", "", 1) = "baa" 3280 * StringUtil.replace("abaa", "a", "z", 0) = "abaa" 3281 * StringUtil.replace("abaa", "a", "z", 1) = "zbaa" 3282 * StringUtil.replace("abaa", "a", "z", 2) = "zbza" 3283 * StringUtil.replace("abaa", "a", "z", -1) = "zbzz" 3284 * </pre> 3285 * </p> 3286 * 3287 * @param text 要扫描的字符串 3288 * @param repl 要搜索的子串 3289 * @param with 替换字符串 3290 * @param max maximum number of values to replace, or <code>-1</code> if no maximum 3291 * 3292 * @return 被替换后的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3293 */ 3294 public static String replace(String text, String repl, String with, int max) { 3295 if ((text == null) || (repl == null) || (with == null) || (repl.length() == 0) 3296 || (max == 0)) { 3297 return text; 3298 } 3299 3300 StringBuffer buf = new StringBuffer(text.length()); 3301 int start = 0; 3302 int end = 0; 3303 3304 while ((end = text.indexOf(repl, start)) != -1) { 3305 buf.append(text.substring(start, end)).append(with); 3306 start = end + repl.length(); 3307 3308 if (--max == 0) { 3309 break; 3310 } 3311 } 3312 3313 buf.append(text.substring(start)); 3314 return buf.toString(); 3315 } 3316 3317 /** 3318 * 将字符串中所有指定的字符,替换成另一个。 3319 * 3320 * <p> 3321 * 如果字符串为<code>null</code>则返回<code>null</code>。 3322 * <pre> 3323 * StringUtil.replaceChars(null, *, *) = null 3324 * StringUtil.replaceChars("", *, *) = "" 3325 * StringUtil.replaceChars("abcba", 'b', 'y') = "aycya" 3326 * StringUtil.replaceChars("abcba", 'z', 'y') = "abcba" 3327 * </pre> 3328 * </p> 3329 * 3330 * @param str 要扫描的字符串 3331 * @param searchChar 要搜索的字符 3332 * @param replaceChar 替换字符 3333 * 3334 * @return 被替换后的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3335 */ 3336 public static String replaceChars(String str, char searchChar, char replaceChar) { 3337 if (str == null) { 3338 return null; 3339 } 3340 3341 return str.replace(searchChar, replaceChar); 3342 } 3343 3344 /** 3345 * 将字符串中所有指定的字符,替换成另一个。 3346 * 3347 * <p> 3348 * 如果字符串为<code>null</code>则返回<code>null</code>。如果搜索字符串为<code>null</code>或空,则返回原字符串。 3349 * </p> 3350 * 3351 * <p> 3352 * 例如: <code>replaceChars("hello", "ho", "jy") = jelly</code>。 3353 * </p> 3354 * 3355 * <p> 3356 * 通常搜索字符串和替换字符串是等长的,如果搜索字符串比替换字符串长,则多余的字符将被删除。 如果搜索字符串比替换字符串短,则缺少的字符将被忽略。 3357 * <pre> 3358 * StringUtil.replaceChars(null, *, *) = null 3359 * StringUtil.replaceChars("", *, *) = "" 3360 * StringUtil.replaceChars("abc", null, *) = "abc" 3361 * StringUtil.replaceChars("abc", "", *) = "abc" 3362 * StringUtil.replaceChars("abc", "b", null) = "ac" 3363 * StringUtil.replaceChars("abc", "b", "") = "ac" 3364 * StringUtil.replaceChars("abcba", "bc", "yz") = "ayzya" 3365 * StringUtil.replaceChars("abcba", "bc", "y") = "ayya" 3366 * StringUtil.replaceChars("abcba", "bc", "yzx") = "ayzya" 3367 * </pre> 3368 * </p> 3369 * 3370 * @param str 要扫描的字符串 3371 * @param searchChars 要搜索的字符串 3372 * @param replaceChars 替换字符串 3373 * 3374 * @return 被替换后的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3375 */ 3376 public static String replaceChars(String str, String searchChars, String replaceChars) { 3377 if ((str == null) || (str.length() == 0) || (searchChars == null) 3378 || (searchChars.length() == 0)) { 3379 return str; 3380 } 3381 3382 char[] chars = str.toCharArray(); 3383 int len = chars.length; 3384 boolean modified = false; 3385 3386 for (int i = 0, isize = searchChars.length(); i < isize; i++) { 3387 char searchChar = searchChars.charAt(i); 3388 3389 if ((replaceChars == null) || (i >= replaceChars.length())) { 3390 // 删除 3391 int pos = 0; 3392 3393 for (int j = 0; j < len; j++) { 3394 if (chars[j] != searchChar) { 3395 chars[pos++] = chars[j]; 3396 } else { 3397 modified = true; 3398 } 3399 } 3400 3401 len = pos; 3402 } else { 3403 // 替换 3404 for (int j = 0; j < len; j++) { 3405 if (chars[j] == searchChar) { 3406 chars[j] = replaceChars.charAt(i); 3407 modified = true; 3408 } 3409 } 3410 } 3411 } 3412 3413 if (!modified) { 3414 return str; 3415 } 3416 3417 return new String(chars, 0, len); 3418 } 3419 3420 /** 3421 * 将指定的子串用另一指定子串覆盖。 3422 * 3423 * <p> 3424 * 如果字符串为<code>null</code>,则返回<code>null</code>。 负的索引值将被看作<code>0</code>,越界的索引值将被设置成字符串的长度相同的值。 3425 * <pre> 3426 * StringUtil.overlay(null, *, *, *) = null 3427 * StringUtil.overlay("", "abc", 0, 0) = "abc" 3428 * StringUtil.overlay("abcdef", null, 2, 4) = "abef" 3429 * StringUtil.overlay("abcdef", "", 2, 4) = "abef" 3430 * StringUtil.overlay("abcdef", "", 4, 2) = "abef" 3431 * StringUtil.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 3432 * StringUtil.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 3433 * StringUtil.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 3434 * StringUtil.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 3435 * StringUtil.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 3436 * StringUtil.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 3437 * </pre> 3438 * </p> 3439 * 3440 * @param str 要扫描的字符串 3441 * @param overlay 用来覆盖的字符串 3442 * @param start 起始索引 3443 * @param end 结束索引 3444 * 3445 * @return 被覆盖后的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3446 */ 3447 public static String overlay(String str, String overlay, int start, int end) { 3448 if (str == null) { 3449 return null; 3450 } 3451 3452 if (overlay == null) { 3453 overlay = EMPTY_STRING; 3454 } 3455 3456 int len = str.length(); 3457 3458 if (start < 0) { 3459 start = 0; 3460 } 3461 3462 if (start > len) { 3463 start = len; 3464 } 3465 3466 if (end < 0) { 3467 end = 0; 3468 } 3469 3470 if (end > len) { 3471 end = len; 3472 } 3473 3474 if (start > end) { 3475 int temp = start; 3476 3477 start = end; 3478 end = temp; 3479 } 3480 3481 return new StringBuffer((len + start) - end + overlay.length() + 1).append( 3482 str.substring(0, start)).append(overlay).append(str.substring(end)).toString(); 3483 } 3484 3485 /* ============================================================================ */ 3486 /* Perl风格的chomp和chop函数。 */ 3487 /* ============================================================================ */ 3488 3489 /** 3490 * 删除字符串末尾的换行符。如果字符串不以换行结尾,则什么也不做。 3491 * 3492 * <p> 3493 * 换行符有三种情形:"<code>\n</code>"、"<code>\r</code>"、"<code>\r\n</code>"。 3494 * <pre> 3495 * StringUtil.chomp(null) = null 3496 * StringUtil.chomp("") = "" 3497 * StringUtil.chomp("abc \r") = "abc " 3498 * StringUtil.chomp("abc\n") = "abc" 3499 * StringUtil.chomp("abc\r\n") = "abc" 3500 * StringUtil.chomp("abc\r\n\r\n") = "abc\r\n" 3501 * StringUtil.chomp("abc\n\r") = "abc\n" 3502 * StringUtil.chomp("abc\n\rabc") = "abc\n\rabc" 3503 * StringUtil.chomp("\r") = "" 3504 * StringUtil.chomp("\n") = "" 3505 * StringUtil.chomp("\r\n") = "" 3506 * </pre> 3507 * </p> 3508 * 3509 * @param str 要处理的字符串 3510 * 3511 * @return 不以换行结尾的字符串,如果原始字串为<code>null</code>,则返回<code>null</code> 3512 */ 3513 public static String chomp(String str) { 3514 if ((str == null) || (str.length() == 0)) { 3515 return str; 3516 } 3517 3518 if (str.length() == 1) { 3519 char ch = str.charAt(0); 3520 3521 if ((ch == '\r') || (ch == '\n')) { 3522 return EMPTY_STRING; 3523 } else { 3524 return str; 3525 } 3526 } 3527 3528 int lastIdx = str.length() - 1; 3529 char last = str.charAt(lastIdx); 3530 3531 if (last == '\n') { 3532 if (str.charAt(lastIdx - 1) == '\r') { 3533 lastIdx--; 3534 } 3535 } else if (last == '\r') { 3536 } else { 3537 lastIdx++; 3538 } 3539 3540 return str.substring(0, lastIdx); 3541 } 3542 3543 /** 3544 * 删除字符串末尾的指定字符串。如果字符串不以该字符串结尾,则什么也不做。 3545 * <pre> 3546 * StringUtil.chomp(null, *) = null 3547 * StringUtil.chomp("", *) = "" 3548 * StringUtil.chomp("foobar", "bar") = "foo" 3549 * StringUtil.chomp("foobar", "baz") = "foobar" 3550 * StringUtil.chomp("foo", "foo") = "" 3551 * StringUtil.chomp("foo ", "foo") = "foo " 3552 * StringUtil.chomp(" foo", "foo") = " " 3553 * StringUtil.chomp("foo", "foooo") = "foo" 3554 * StringUtil.chomp("foo", "") = "foo" 3555 * StringUtil.chomp("foo", null) = "foo" 3556 * </pre> 3557 * 3558 * @param str 要处理的字符串 3559 * @param separator 要删除的字符串 3560 * 3561 * @return 不以指定字符串结尾的字符串,如果原始字串为<code>null</code>,则返回<code>null</code> 3562 */ 3563 public static String chomp(String str, String separator) { 3564 if ((str == null) || (str.length() == 0) || (separator == null)) { 3565 return str; 3566 } 3567 3568 if (str.endsWith(separator)) { 3569 return str.substring(0, str.length() - separator.length()); 3570 } 3571 3572 return str; 3573 } 3574 3575 /** 3576 * 删除最后一个字符。 3577 * 3578 * <p> 3579 * 如果字符串以<code>\r\n</code>结尾,则同时删除它们。 3580 * <pre> 3581 * StringUtil.chop(null) = null 3582 * StringUtil.chop("") = "" 3583 * StringUtil.chop("abc \r") = "abc " 3584 * StringUtil.chop("abc\n") = "abc" 3585 * StringUtil.chop("abc\r\n") = "abc" 3586 * StringUtil.chop("abc") = "ab" 3587 * StringUtil.chop("abc\nabc") = "abc\nab" 3588 * StringUtil.chop("a") = "" 3589 * StringUtil.chop("\r") = "" 3590 * StringUtil.chop("\n") = "" 3591 * StringUtil.chop("\r\n") = "" 3592 * </pre> 3593 * </p> 3594 * 3595 * @param str 要处理的字符串 3596 * 3597 * @return 删除最后一个字符的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3598 */ 3599 public static String chop(String str) { 3600 if (str == null) { 3601 return null; 3602 } 3603 3604 int strLen = str.length(); 3605 3606 if (strLen < 2) { 3607 return EMPTY_STRING; 3608 } 3609 3610 int lastIdx = strLen - 1; 3611 String ret = str.substring(0, lastIdx); 3612 char last = str.charAt(lastIdx); 3613 3614 if (last == '\n') { 3615 if (ret.charAt(lastIdx - 1) == '\r') { 3616 return ret.substring(0, lastIdx - 1); 3617 } 3618 } 3619 3620 return ret; 3621 } 3622 3623 /* ============================================================================ */ 3624 /* 重复/对齐字符串。 */ 3625 /* ============================================================================ */ 3626 3627 /** 3628 * 将指定字符串重复n遍。 3629 * <pre> 3630 * StringUtil.repeat(null, 2) = null 3631 * StringUtil.repeat("", 0) = "" 3632 * StringUtil.repeat("", 2) = "" 3633 * StringUtil.repeat("a", 3) = "aaa" 3634 * StringUtil.repeat("ab", 2) = "abab" 3635 * StringUtil.repeat("abcd", 2) = "abcdabcd" 3636 * StringUtil.repeat("a", -2) = "" 3637 * </pre> 3638 * 3639 * @param str 要重复的字符串 3640 * @param repeat 重复次数,如果小于<code>0</code>,则看作<code>0</code> 3641 * 3642 * @return 重复n次的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code> 3643 */ 3644 public static String repeat(String str, int repeat) { 3645 if (str == null) { 3646 return null; 3647 } 3648 3649 if (repeat <= 0) { 3650 return EMPTY_STRING; 3651 } 3652 3653 int inputLength = str.length(); 3654 3655 if ((repeat == 1) || (inputLength == 0)) { 3656 return str; 3657 } 3658 3659 int outputLength = inputLength * repeat; 3660 3661 switch (inputLength) { 3662 case 1: 3663 3664 char ch = str.charAt(0); 3665 char[] output1 = new char[outputLength]; 3666 3667 for (int i = repeat - 1; i >= 0; i--) { 3668 output1[i] = ch; 3669 } 3670 3671 return new String(output1); 3672 3673 case 2: 3674 3675 char ch0 = str.charAt(0); 3676 char ch1 = str.charAt(1); 3677 char[] output2 = new char[outputLength]; 3678 3679 for (int i = (repeat * 2) - 2; i >= 0; i--, i--) { 3680 output2[i] = ch0; 3681 output2[i + 1] = ch1; 3682 } 3683 3684 return new String(output2); 3685 3686 default: 3687 3688 StringBuffer buf = new StringBuffer(outputLength); 3689 3690 for (int i = 0; i < repeat; i++) { 3691 buf.append(str); 3692 } 3693 3694 return buf.toString(); 3695 } 3696 } 3697 3698 /** 3699 * 扩展并左对齐字符串,用空格<code>' '</code>填充右边。 3700 * <pre> 3701 * StringUtil.alignLeft(null, *) = null 3702 * StringUtil.alignLeft("", 3) = " " 3703 * StringUtil.alignLeft("bat", 3) = "bat" 3704 * StringUtil.alignLeft("bat", 5) = "bat " 3705 * StringUtil.alignLeft("bat", 1) = "bat" 3706 * StringUtil.alignLeft("bat", -1) = "bat" 3707 * </pre> 3708 * 3709 * @param str 要对齐的字符串 3710 * @param size 扩展字符串到指定宽度 3711 * 3712 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3713 */ 3714 public static String alignLeft(String str, int size) { 3715 return alignLeft(str, size, ' '); 3716 } 3717 3718 /** 3719 * 扩展并左对齐字符串,用指定字符填充右边。 3720 * <pre> 3721 * StringUtil.alignLeft(null, *, *) = null 3722 * StringUtil.alignLeft("", 3, 'z') = "zzz" 3723 * StringUtil.alignLeft("bat", 3, 'z') = "bat" 3724 * StringUtil.alignLeft("bat", 5, 'z') = "batzz" 3725 * StringUtil.alignLeft("bat", 1, 'z') = "bat" 3726 * StringUtil.alignLeft("bat", -1, 'z') = "bat" 3727 * </pre> 3728 * 3729 * @param str 要对齐的字符串 3730 * @param size 扩展字符串到指定宽度 3731 * @param padChar 填充字符 3732 * 3733 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3734 */ 3735 public static String alignLeft(String str, int size, char padChar) { 3736 if (str == null) { 3737 return null; 3738 } 3739 3740 int pads = size - str.length(); 3741 3742 if (pads <= 0) { 3743 return str; 3744 } 3745 3746 return alignLeft(str, size, String.valueOf(padChar)); 3747 } 3748 3749 /** 3750 * 扩展并左对齐字符串,用指定字符串填充右边。 3751 * <pre> 3752 * StringUtil.alignLeft(null, *, *) = null 3753 * StringUtil.alignLeft("", 3, "z") = "zzz" 3754 * StringUtil.alignLeft("bat", 3, "yz") = "bat" 3755 * StringUtil.alignLeft("bat", 5, "yz") = "batyz" 3756 * StringUtil.alignLeft("bat", 8, "yz") = "batyzyzy" 3757 * StringUtil.alignLeft("bat", 1, "yz") = "bat" 3758 * StringUtil.alignLeft("bat", -1, "yz") = "bat" 3759 * StringUtil.alignLeft("bat", 5, null) = "bat " 3760 * StringUtil.alignLeft("bat", 5, "") = "bat " 3761 * </pre> 3762 * 3763 * @param str 要对齐的字符串 3764 * @param size 扩展字符串到指定宽度 3765 * @param padStr 填充字符串 3766 * 3767 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3768 */ 3769 public static String alignLeft(String str, int size, String padStr) { 3770 if (str == null) { 3771 return null; 3772 } 3773 3774 if ((padStr == null) || (padStr.length() == 0)) { 3775 padStr = " "; 3776 } 3777 3778 int padLen = padStr.length(); 3779 int strLen = str.length(); 3780 int pads = size - strLen; 3781 3782 if (pads <= 0) { 3783 return str; 3784 } 3785 3786 if (pads == padLen) { 3787 return str.concat(padStr); 3788 } else if (pads < padLen) { 3789 return str.concat(padStr.substring(0, pads)); 3790 } else { 3791 char[] padding = new char[pads]; 3792 char[] padChars = padStr.toCharArray(); 3793 3794 for (int i = 0; i < pads; i++) { 3795 padding[i] = padChars[i % padLen]; 3796 } 3797 3798 return str.concat(new String(padding)); 3799 } 3800 } 3801 3802 /** 3803 * 扩展并右对齐字符串,用空格<code>' '</code>填充左边。 3804 * <pre> 3805 * StringUtil.alignRight(null, *) = null 3806 * StringUtil.alignRight("", 3) = " " 3807 * StringUtil.alignRight("bat", 3) = "bat" 3808 * StringUtil.alignRight("bat", 5) = " bat" 3809 * StringUtil.alignRight("bat", 1) = "bat" 3810 * StringUtil.alignRight("bat", -1) = "bat" 3811 * </pre> 3812 * 3813 * @param str 要对齐的字符串 3814 * @param size 扩展字符串到指定宽度 3815 * 3816 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3817 */ 3818 public static String alignRight(String str, int size) { 3819 return alignRight(str, size, ' '); 3820 } 3821 3822 /** 3823 * 扩展并右对齐字符串,用指定字符填充左边。 3824 * <pre> 3825 * StringUtil.alignRight(null, *, *) = null 3826 * StringUtil.alignRight("", 3, 'z') = "zzz" 3827 * StringUtil.alignRight("bat", 3, 'z') = "bat" 3828 * StringUtil.alignRight("bat", 5, 'z') = "zzbat" 3829 * StringUtil.alignRight("bat", 1, 'z') = "bat" 3830 * StringUtil.alignRight("bat", -1, 'z') = "bat" 3831 * </pre> 3832 * 3833 * @param str 要对齐的字符串 3834 * @param size 扩展字符串到指定宽度 3835 * @param padChar 填充字符 3836 * 3837 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3838 */ 3839 public static String alignRight(String str, int size, char padChar) { 3840 if (str == null) { 3841 return null; 3842 } 3843 3844 int pads = size - str.length(); 3845 3846 if (pads <= 0) { 3847 return str; 3848 } 3849 3850 return alignRight(str, size, String.valueOf(padChar)); 3851 } 3852 3853 /** 3854 * 扩展并右对齐字符串,用指定字符串填充左边。 3855 * <pre> 3856 * StringUtil.alignRight(null, *, *) = null 3857 * StringUtil.alignRight("", 3, "z") = "zzz" 3858 * StringUtil.alignRight("bat", 3, "yz") = "bat" 3859 * StringUtil.alignRight("bat", 5, "yz") = "yzbat" 3860 * StringUtil.alignRight("bat", 8, "yz") = "yzyzybat" 3861 * StringUtil.alignRight("bat", 1, "yz") = "bat" 3862 * StringUtil.alignRight("bat", -1, "yz") = "bat" 3863 * StringUtil.alignRight("bat", 5, null) = " bat" 3864 * StringUtil.alignRight("bat", 5, "") = " bat" 3865 * </pre> 3866 * 3867 * @param str 要对齐的字符串 3868 * @param size 扩展字符串到指定宽度 3869 * @param padStr 填充字符串 3870 * 3871 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3872 */ 3873 public static String alignRight(String str, int size, String padStr) { 3874 if (str == null) { 3875 return null; 3876 } 3877 3878 if ((padStr == null) || (padStr.length() == 0)) { 3879 padStr = " "; 3880 } 3881 3882 int padLen = padStr.length(); 3883 int strLen = str.length(); 3884 int pads = size - strLen; 3885 3886 if (pads <= 0) { 3887 return str; 3888 } 3889 3890 if (pads == padLen) { 3891 return padStr.concat(str); 3892 } else if (pads < padLen) { 3893 return padStr.substring(0, pads).concat(str); 3894 } else { 3895 char[] padding = new char[pads]; 3896 char[] padChars = padStr.toCharArray(); 3897 3898 for (int i = 0; i < pads; i++) { 3899 padding[i] = padChars[i % padLen]; 3900 } 3901 3902 return new String(padding).concat(str); 3903 } 3904 } 3905 3906 /** 3907 * 扩展并居中字符串,用空格<code>' '</code>填充两边。 3908 * <pre> 3909 * StringUtil.center(null, *) = null 3910 * StringUtil.center("", 4) = " " 3911 * StringUtil.center("ab", -1) = "ab" 3912 * StringUtil.center("ab", 4) = " ab " 3913 * StringUtil.center("abcd", 2) = "abcd" 3914 * StringUtil.center("a", 4) = " a " 3915 * </pre> 3916 * 3917 * @param str 要对齐的字符串 3918 * @param size 扩展字符串到指定宽度 3919 * 3920 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3921 */ 3922 public static String center(String str, int size) { 3923 return center(str, size, ' '); 3924 } 3925 3926 /** 3927 * 扩展并居中字符串,用指定字符填充两边。 3928 * <pre> 3929 * StringUtil.center(null, *, *) = null 3930 * StringUtil.center("", 4, ' ') = " " 3931 * StringUtil.center("ab", -1, ' ') = "ab" 3932 * StringUtil.center("ab", 4, ' ') = " ab " 3933 * StringUtil.center("abcd", 2, ' ') = "abcd" 3934 * StringUtil.center("a", 4, ' ') = " a " 3935 * StringUtil.center("a", 4, 'y') = "yayy" 3936 * </pre> 3937 * 3938 * @param str 要对齐的字符串 3939 * @param size 扩展字符串到指定宽度 3940 * @param padChar 填充字符 3941 * 3942 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3943 */ 3944 public static String center(String str, int size, char padChar) { 3945 if ((str == null) || (size <= 0)) { 3946 return str; 3947 } 3948 3949 int strLen = str.length(); 3950 int pads = size - strLen; 3951 3952 if (pads <= 0) { 3953 return str; 3954 } 3955 3956 str = alignRight(str, strLen + (pads / 2), padChar); 3957 str = alignLeft(str, size, padChar); 3958 return str; 3959 } 3960 3961 /** 3962 * 扩展并居中字符串,用指定字符串填充两边。 3963 * <pre> 3964 * StringUtil.center(null, *, *) = null 3965 * StringUtil.center("", 4, " ") = " " 3966 * StringUtil.center("ab", -1, " ") = "ab" 3967 * StringUtil.center("ab", 4, " ") = " ab " 3968 * StringUtil.center("abcd", 2, " ") = "abcd" 3969 * StringUtil.center("a", 4, " ") = " a " 3970 * StringUtil.center("a", 4, "yz") = "yayz" 3971 * StringUtil.center("abc", 7, null) = " abc " 3972 * StringUtil.center("abc", 7, "") = " abc " 3973 * </pre> 3974 * 3975 * @param str 要对齐的字符串 3976 * @param size 扩展字符串到指定宽度 3977 * @param padStr 填充字符串 3978 * 3979 * @return 扩展后的字符串,如果字符串为<code>null</code>,则返回<code>null</code> 3980 */ 3981 public static String center(String str, int size, String padStr) { 3982 if ((str == null) || (size <= 0)) { 3983 return str; 3984 } 3985 3986 if ((padStr == null) || (padStr.length() == 0)) { 3987 padStr = " "; 3988 } 3989 3990 int strLen = str.length(); 3991 int pads = size - strLen; 3992 3993 if (pads <= 0) { 3994 return str; 3995 } 3996 3997 str = alignRight(str, strLen + (pads / 2), padStr); 3998 str = alignLeft(str, size, padStr); 3999 return str; 4000 } 4001 4002 /* ============================================================================ */ 4003 /* 反转字符串。 */ 4004 /* ============================================================================ */ 4005 4006 /** 4007 * 反转字符串中的字符顺序。 4008 * 4009 * <p> 4010 * 如果字符串为<code>null</code>,则返回<code>null</code>。 4011 * </p> 4012 * <pre> 4013 * StringUtil.reverse(null) = null 4014 * StringUtil.reverse("") = "" 4015 * StringUtil.reverse("bat") = "tab" 4016 * </pre> 4017 * 4018 * @param str 要反转的字符串 4019 * 4020 * @return 反转后的字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 4021 */ 4022 public static String reverse(String str) { 4023 if ((str == null) || (str.length() == 0)) { 4024 return str; 4025 } 4026 4027 return new StringBuffer(str).reverse().toString(); 4028 } 4029 4030 /** 4031 * 反转指定分隔符分隔的各子串的顺序。 4032 * 4033 * <p> 4034 * 如果字符串为<code>null</code>,则返回<code>null</code>。 4035 * </p> 4036 * <pre> 4037 * StringUtil.reverseDelimited(null, *) = null 4038 * StringUtil.reverseDelimited("", *) = "" 4039 * StringUtil.reverseDelimited("a.b.c", 'x') = "a.b.c" 4040 * StringUtil.reverseDelimited("a.b.c", '.') = "c.b.a" 4041 * </pre> 4042 * 4043 * @param str 要反转的字符串 4044 * @param separatorChar 分隔符 4045 * 4046 * @return 反转后的字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 4047 */ 4048 public static String reverseDelimited(String str, char separatorChar) { 4049 if (str == null) { 4050 return null; 4051 } 4052 4053 String[] strs = split(str, separatorChar); 4054 4055 ArrayUtil.reverse(strs); 4056 4057 return join(strs, separatorChar); 4058 } 4059 4060 /** 4061 * 反转指定分隔符分隔的各子串的顺序。 4062 * 4063 * <p> 4064 * 如果字符串为<code>null</code>,则返回<code>null</code>。 4065 * </p> 4066 * <pre> 4067 * StringUtil.reverseDelimited(null, *, *) = null 4068 * StringUtil.reverseDelimited("", *, *) = "" 4069 * StringUtil.reverseDelimited("a.b.c", null, null) = "a.b.c" 4070 * StringUtil.reverseDelimited("a.b.c", "", null) = "a.b.c" 4071 * StringUtil.reverseDelimited("a.b.c", ".", ",") = "c,b,a" 4072 * StringUtil.reverseDelimited("a.b.c", ".", null) = "c b a" 4073 * </pre> 4074 * 4075 * @param str 要反转的字符串 4076 * @param separatorChars 分隔符,如果为<code>null</code>,则默认使用空白字符 4077 * @param separator 用来连接子串的分隔符,如果为<code>null</code>,默认使用空格 4078 * 4079 * @return 反转后的字符串,如果原字符串为<code>null</code>,则返回<code>null</code> 4080 */ 4081 public static String reverseDelimited(String str, String separatorChars, String separator) { 4082 if (str == null) { 4083 return null; 4084 } 4085 4086 String[] strs = split(str, separatorChars); 4087 4088 ArrayUtil.reverse(strs); 4089 4090 if (separator == null) { 4091 return join(strs, ' '); 4092 } 4093 4094 return join(strs, separator); 4095 } 4096 4097 /* ============================================================================ */ 4098 /* 取得字符串的缩略。 */ 4099 /* ============================================================================ */ 4100 4101 /** 4102 * 将字符串转换成指定长度的缩略,例如: 将"Now is the time for all good men"转换成"Now is the time for..."。 4103 * 4104 * <ul> 4105 * <li> 4106 * 如果<code>str</code>比<code>maxWidth</code>短,直接返回; 4107 * </li> 4108 * <li> 4109 * 否则将它转换成缩略:<code>substring(str, 0, max-3) + "..."</code>; 4110 * </li> 4111 * <li> 4112 * 如果<code>maxWidth</code>小于<code>4</code>抛出<code>IllegalArgumentException</code>; 4113 * </li> 4114 * <li> 4115 * 返回的字符串不可能长于指定的<code>maxWidth</code>。 4116 * </li> 4117 * </ul> 4118 * 4119 * <pre> 4120 * StringUtil.abbreviate(null, *) = null 4121 * StringUtil.abbreviate("", 4) = "" 4122 * StringUtil.abbreviate("abcdefg", 6) = "abc..." 4123 * StringUtil.abbreviate("abcdefg", 7) = "abcdefg" 4124 * StringUtil.abbreviate("abcdefg", 8) = "abcdefg" 4125 * StringUtil.abbreviate("abcdefg", 4) = "a..." 4126 * StringUtil.abbreviate("abcdefg", 3) = IllegalArgumentException 4127 * </pre> 4128 * 4129 * @param str 要检查的字符串 4130 * @param maxWidth 最大长度,不小于<code>4</code>,如果小于<code>4</code>,则看作<code>4</code> 4131 * 4132 * @return 字符串缩略,如果原始字符串为<code>null</code>则返回<code>null</code> 4133 */ 4134 public static String abbreviate(String str, int maxWidth) { 4135 return abbreviate(str, 0, maxWidth); 4136 } 4137 4138 /** 4139 * 将字符串转换成指定长度的缩略,例如: 将"Now is the time for all good men"转换成"...is the time for..."。 4140 * 4141 * <p> 4142 * 和<code>abbreviate(String, int)</code>类似,但是增加了一个“左边界”偏移量。 4143 * 注意,“左边界”处的字符未必出现在结果字符串的最左边,但一定出现在结果字符串中。 4144 * </p> 4145 * 4146 * <p> 4147 * 返回的字符串不可能长于指定的<code>maxWidth</code>。 4148 * <pre> 4149 * StringUtil.abbreviate(null, *, *) = null 4150 * StringUtil.abbreviate("", 0, 4) = "" 4151 * StringUtil.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 4152 * StringUtil.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 4153 * StringUtil.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 4154 * StringUtil.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 4155 * StringUtil.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 4156 * StringUtil.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 4157 * StringUtil.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 4158 * StringUtil.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 4159 * StringUtil.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 4160 * StringUtil.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException 4161 * StringUtil.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException 4162 * </pre> 4163 * </p> 4164 * 4165 * @param str 要检查的字符串 4166 * @param offset 左边界偏移量 4167 * @param maxWidth 最大长度,不小于<code>4</code>,如果小于<code>4</code>,则看作<code>4</code> 4168 * 4169 * @return 字符串缩略,如果原始字符串为<code>null</code>则返回<code>null</code> 4170 */ 4171 public static String abbreviate(String str, int offset, int maxWidth) { 4172 if (str == null) { 4173 return null; 4174 } 4175 4176 // 调整最大宽度 4177 if (maxWidth < 4) { 4178 maxWidth = 4; 4179 } 4180 4181 if (str.length() <= maxWidth) { 4182 return str; 4183 } 4184 4185 if (offset > str.length()) { 4186 offset = str.length(); 4187 } 4188 4189 if ((str.length() - offset) < (maxWidth - 3)) { 4190 offset = str.length() - (maxWidth - 3); 4191 } 4192 4193 if (offset <= 4) { 4194 return str.substring(0, maxWidth - 3) + "..."; 4195 } 4196 4197 // 调整最大宽度 4198 if (maxWidth < 7) { 4199 maxWidth = 7; 4200 } 4201 4202 if ((offset + (maxWidth - 3)) < str.length()) { 4203 return "..." + abbreviate(str.substring(offset), maxWidth - 3); 4204 } 4205 4206 return "..." + str.substring(str.length() - (maxWidth - 3)); 4207 } 4208 4209 /* ============================================================================ */ 4210 /* 比较两个字符串的异同。 */ 4211 /* */ 4212 /* 查找字符串之间的差异,比较字符串的相似度。 */ 4213 /* ============================================================================ */ 4214 4215 /** 4216 * 比较两个字符串,取得第二个字符串中,和第一个字符串不同的部分。 4217 * <pre> 4218 * StringUtil.difference("i am a machine", "i am a robot") = "robot" 4219 * StringUtil.difference(null, null) = null 4220 * StringUtil.difference("", "") = "" 4221 * StringUtil.difference("", null) = "" 4222 * StringUtil.difference("", "abc") = "abc" 4223 * StringUtil.difference("abc", "") = "" 4224 * StringUtil.difference("abc", "abc") = "" 4225 * StringUtil.difference("ab", "abxyz") = "xyz" 4226 * StringUtil.difference("abcde", "abxyz") = "xyz" 4227 * StringUtil.difference("abcde", "xyz") = "xyz" 4228 * </pre> 4229 * 4230 * @param str1 字符串1 4231 * @param str2 字符串2 4232 * 4233 * @return 第二个字符串中,和第一个字符串不同的部分。如果两个字符串相同,则返回空字符串<code>""</code> 4234 */ 4235 public static String difference(String str1, String str2) { 4236 if (str1 == null) { 4237 return str2; 4238 } 4239 4240 if (str2 == null) { 4241 return str1; 4242 } 4243 4244 int index = indexOfDifference(str1, str2); 4245 4246 if (index == -1) { 4247 return EMPTY_STRING; 4248 } 4249 4250 return str2.substring(index); 4251 } 4252 4253 /** 4254 * 比较两个字符串,取得两字符串开始不同的索引值。 4255 * <pre> 4256 * StringUtil.indexOfDifference("i am a machine", "i am a robot") = 7 4257 * StringUtil.indexOfDifference(null, null) = -1 4258 * StringUtil.indexOfDifference("", null) = -1 4259 * StringUtil.indexOfDifference("", "") = -1 4260 * StringUtil.indexOfDifference("", "abc") = 0 4261 * StringUtil.indexOfDifference("abc", "") = 0 4262 * StringUtil.indexOfDifference("abc", "abc") = -1 4263 * StringUtil.indexOfDifference("ab", "abxyz") = 2 4264 * StringUtil.indexOfDifference("abcde", "abxyz") = 2 4265 * StringUtil.indexOfDifference("abcde", "xyz") = 0 4266 * </pre> 4267 * 4268 * @param str1 字符串1 4269 * @param str2 字符串2 4270 * 4271 * @return 两字符串开始产生差异的索引值,如果两字符串相同,则返回<code>-1</code> 4272 */ 4273 public static int indexOfDifference(String str1, String str2) { 4274 if ((str1 == str2) || (str1 == null) || (str2 == null)) { 4275 return -1; 4276 } 4277 4278 int i; 4279 4280 for (i = 0; (i < str1.length()) && (i < str2.length()); ++i) { 4281 if (str1.charAt(i) != str2.charAt(i)) { 4282 break; 4283 } 4284 } 4285 4286 if ((i < str2.length()) || (i < str1.length())) { 4287 return i; 4288 } 4289 4290 return -1; 4291 } 4292 4293 /** 4294 * 取得两个字符串的相似度,<code>0</code>代表字符串相等,数字越大表示字符串越不像。 4295 * 4296 * <p> 4297 * 这个算法取自<a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a>。 4298 * 它计算的是从字符串1转变到字符串2所需要的删除、插入和替换的步骤数。 4299 * </p> 4300 * <pre> 4301 * StringUtil.getLevenshteinDistance(null, *) = IllegalArgumentException 4302 * StringUtil.getLevenshteinDistance(*, null) = IllegalArgumentException 4303 * StringUtil.getLevenshteinDistance("","") = 0 4304 * StringUtil.getLevenshteinDistance("","a") = 1 4305 * StringUtil.getLevenshteinDistance("aaapppp", "") = 7 4306 * StringUtil.getLevenshteinDistance("frog", "fog") = 1 4307 * StringUtil.getLevenshteinDistance("fly", "ant") = 3 4308 * StringUtil.getLevenshteinDistance("elephant", "hippo") = 7 4309 * StringUtil.getLevenshteinDistance("hippo", "elephant") = 7 4310 * StringUtil.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 4311 * StringUtil.getLevenshteinDistance("hello", "hallo") = 1 4312 * </pre> 4313 * 4314 * @param s 第一个字符串,如果是<code>null</code>,则看作空字符串 4315 * @param t 第二个字符串,如果是<code>null</code>,则看作空字符串 4316 * 4317 * @return 相似度值 4318 */ 4319 public static int getLevenshteinDistance(String s, String t) { 4320 s = defaultIfNull(s); 4321 t = defaultIfNull(t); 4322 4323 int[][] d; // matrix 4324 int n; // length of s 4325 int m; // length of t 4326 int i; // iterates through s 4327 int j; // iterates through t 4328 char s_i; // ith character of s 4329 char t_j; // jth character of t 4330 int cost; // cost 4331 4332 // Step 1 4333 n = s.length(); 4334 m = t.length(); 4335 4336 if (n == 0) { 4337 return m; 4338 } 4339 4340 if (m == 0) { 4341 return n; 4342 } 4343 4344 d = new int[n + 1][m + 1]; 4345 4346 // Step 2 4347 for (i = 0; i <= n; i++) { 4348 d[i][0] = i; 4349 } 4350 4351 for (j = 0; j <= m; j++) { 4352 d[0][j] = j; 4353 } 4354 4355 // Step 3 4356 for (i = 1; i <= n; i++) { 4357 s_i = s.charAt(i - 1); 4358 4359 // Step 4 4360 for (j = 1; j <= m; j++) { 4361 t_j = t.charAt(j - 1); 4362 4363 // Step 5 4364 if (s_i == t_j) { 4365 cost = 0; 4366 } else { 4367 cost = 1; 4368 } 4369 4370 // Step 6 4371 d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); 4372 } 4373 } 4374 4375 // Step 7 4376 return d[n][m]; 4377 } 4378 4379 /** 4380 * 取得最小数。 4381 * 4382 * @param a 整数1 4383 * @param b 整数2 4384 * @param c 整数3 4385 * 4386 * @return 三个数中的最小值 4387 */ 4388 private static int min(int a, int b, int c) { 4389 if (b < a) { 4390 a = b; 4391 } 4392 4393 if (c < a) { 4394 a = c; 4395 } 4396 4397 return a; 4398 } 4399 }
如果本文对您有帮助,点一下右下角的“推荐”