Apache-Commons-Lang 使用笔记
Apache-Commons-Lang使用笔记
Apache Commons Lang 官网
https://commons.apache.org/proper/commons-lang/
Apache Commons Lang 3 官方API文档
https://commons.apache.org/proper/commons-lang/javadocs/api-release/index.html
commons-text
LevenshteinDistance 编辑距离
编辑距离,又叫 Levenshtein 距离,莱文斯坦距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。
int distance = LevenshteinDistance.getDefaultInstance().apply(str1, str2);
测试计算 1000 对 20-50 随机长度字符串的编辑距离耗时约 55 毫秒。
@Test
public void testEditDistance() {
int count = 1000;
long ts = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
String str1 = RandomStringUtils.randomAlphanumeric(20, 50);
String str2 = RandomStringUtils.randomAlphanumeric(20, 50);
int distance = LevenshteinDistance.getDefaultInstance().apply(str1, str2);
log.info("edit distance of {} and {} is {}", str1, str2, distance);
}
log.info("cal {} edit distance took {} ms", count, System.currentTimeMillis() - ts);
}
结果 cal 1000 edit distance took 55 ms
StopWatch
StopWatch 是 apache commons lang3 包下的一个任务执行时间监视器
主要方法:
start(); //开始计时
split(); //设置split点
getSplitTime(); //获取从start 到 最后一次split的毫秒时间。调用start()方法到最后一次调用split()方法耗用的时间
reset(); //重置计时
suspend(); //暂停计时, 直到调用resume()后才恢复计时
resume(); //恢复计时
stop(); //停止计时
getTime(); //如果已stop(),统计start到stop的毫秒时间;如果未stop,统计从start到现在的毫秒时间
import org.apache.commons.lang3.time.StopWatch;
public class StopWatchTest
{
public static void main(String[] args) throws InterruptedException {
StopWatch watch = new StopWatch();
watch.start(); // 开始计时
Thread.sleep(1000)
System.out.println(watch.getTime()); // 统计从start开始经历的时间
watch.split(); //设置分割点
//统计计时点
Thread.sleep(1000);
System.out.println(watch.getTime() - watch.getSplitTime()); //当前时间到上一次分割点的时间差
watch.split(); //设置分割点
Thread.sleep(1000);
System.out.println(watch.getTime() - watch.getSplitTime()); //当前时间到上一次分割点的时间差
watch.split(); //设置分割点
System.out.println(watch.getTime()); // 统计从start开始经历的时间,即整个方法所用的时间
}
}
StringUtils
package org.apache.commons.lang3;
public class StringUtils{}
substringBefore() 分隔符首次出现前的子串
返回字符串 str 中分隔符 separator 第一次出现位置左侧的子串,分隔符本身不返回。
public static String substringBefore(final String str, final String separator) {
if (isEmpty(str) || separator == null) {
return str;
}
if (separator.isEmpty()) {
return EMPTY;
}
final int pos = str.indexOf(separator);
if (pos == INDEX_NOT_FOUND) {
return str;
}
return str.substring(0, pos);
}
示例:
StringUtils.substringBefore(null, *) = null
StringUtils.substringBefore("", *) = ""
StringUtils.substringBefore("abc", "a") = ""
StringUtils.substringBefore("abcba", "b") = "a"
StringUtils.substringBefore("abc", "c") = "ab"
StringUtils.substringBefore("abc", "d") = "abc"
StringUtils.substringBefore("abc", "") = ""
StringUtils.substringBefore("abc", null) = "abc"
substringAfter() 分隔符首次出现后的子串
返回字符串 str 中分隔符 separator 第一次出现位置右侧的子串,分隔符本身不返回。
public static String substringAfter(final String str, final String separator) {
if (isEmpty(str)) {
return str;
}
if (separator == null) {
return EMPTY;
}
final int pos = str.indexOf(separator);
if (pos == INDEX_NOT_FOUND) {
return EMPTY;
}
return str.substring(pos + separator.length());
}
示例:
StringUtils.substringAfter(null, *) = null
StringUtils.substringAfter("", *) = ""
StringUtils.substringAfter(*, null) = ""
StringUtils.substringAfter("abc", "a") = "bc"
StringUtils.substringAfter("abcba", "b") = "cba"
StringUtils.substringAfter("abc", "c") = ""
StringUtils.substringAfter("abc", "d") = ""
StringUtils.substringAfter("abc", "") = "abc"
substringBeforeLast() 分隔符最后出现前的子串
public static String substringBeforeLast(final String str, final String separator) {
if (isEmpty(str) || isEmpty(separator)) {
return str;
}
final int pos = str.lastIndexOf(separator);
if (pos == INDEX_NOT_FOUND) {
return str;
}
return str.substring(0, pos);
}
StringUtils.substringBeforeLast(null, *) = null
StringUtils.substringBeforeLast("", *) = ""
StringUtils.substringBeforeLast("abcba", "b") = "abc"
StringUtils.substringBeforeLast("abc", "c") = "ab"
StringUtils.substringBeforeLast("a", "a") = ""
StringUtils.substringBeforeLast("a", "z") = "a"
StringUtils.substringBeforeLast("a", null) = "a"
StringUtils.substringBeforeLast("a", "") = "a"
substringAfterLast() 分隔符最后出现后的子串
返回字符串 str 中分隔符 separator 最后一次出现位置右侧的子串,分隔符本身不返回。
public static String substringAfterLast(final String str, final String separator) {
if (isEmpty(str)) {
return str;
}
if (isEmpty(separator)) {
return EMPTY;
}
final int pos = str.lastIndexOf(separator);
if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
return EMPTY;
}
return str.substring(pos + separator.length());
}
示例:
StringUtils.substringAfterLast(null, *) = null
StringUtils.substringAfterLast("", *) = ""
StringUtils.substringAfterLast(*, "") = ""
StringUtils.substringAfterLast(*, null) = ""
StringUtils.substringAfterLast("abc", "a") = "bc"
StringUtils.substringAfterLast("abcba", "b") = "a"
StringUtils.substringAfterLast("abc", "c") = ""
StringUtils.substringAfterLast("a", "a") = ""
StringUtils.substringAfterLast("a", "z") = ""
substringBetween() 两个分隔符之间的子串
public static String substringBetween(final String str, final String open, final String close)
StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
StringUtils.substringBetween(null, *, *) = null
StringUtils.substringBetween(*, null, *) = null
StringUtils.substringBetween(*, *, null) = null
StringUtils.substringBetween("", "", "") = ""
StringUtils.substringBetween("", "", "]") = null
StringUtils.substringBetween("", "[", "]") = null
StringUtils.substringBetween("yabcz", "", "") = ""
StringUtils.substringBetween("yabcz", "y", "z") = "abc"
StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc"
isNotBlank() 非空白
public static boolean isNotBlank(CharSequence cs)
当字符传非null、非””,并且不是全部空白(空格)时,才返回true
StringUtils.isNotBlank(null) = false
StringUtils.isNotBlank("") = false
StringUtils.isNotBlank(" ") = false
StringUtils.isNotBlank("bob") = true
StringUtils.isNotBlank(" bob ") = true
isNotEmpty() 非空
public static boolean isNotEmpty(CharSequence cs)
当字符串非null,非””时返回true,空白返回true
StringUtils.isNotEmpty(null) = false
StringUtils.isNotEmpty("") = false
StringUtils.isNotEmpty(" ") = true
StringUtils.isNotEmpty("bob") = true
StringUtils.isNotEmpty(" bob ") = true
isNoneBlank() 全部非空白
public static boolean isNoneBlank(CharSequence... css)
当所有参数字符串都 非null、非””、非空白 时,返回true
public static boolean isNoneBlank(final CharSequence... css) {
return !isAnyBlank(css);
}
StringUtils.isNoneBlank((String) null) = false
StringUtils.isNoneBlank((String[]) null) = true
StringUtils.isNoneBlank(null, "foo") = false
StringUtils.isNoneBlank(null, null) = false
StringUtils.isNoneBlank("", "bar") = false
StringUtils.isNoneBlank("bob", "") = false
StringUtils.isNoneBlank(" bob ", null) = false
StringUtils.isNoneBlank(" ", "bar") = false
StringUtils.isNoneBlank(new String[] {}) = true
StringUtils.isNoneBlank(new String[]{""}) = false
StringUtils.isNoneBlank("foo", "bar") = true
isNoneEmpty() 全部非空
public static boolean isNoneEmpty(CharSequence... css)
当所有参数字符串都 非null、非”” 时,返回true
StringUtils.isNoneEmpty((String) null) = false
StringUtils.isNoneEmpty((String[]) null) = true
StringUtils.isNoneEmpty(null, "foo") = false
StringUtils.isNoneEmpty("", "bar") = false
StringUtils.isNoneEmpty("bob", "") = false
StringUtils.isNoneEmpty(" bob ", null) = false
StringUtils.isNoneEmpty(new String[] {}) = true
StringUtils.isNoneEmpty(new String[]{""}) = false
StringUtils.isNoneEmpty(" ", "bar") = true
StringUtils.isNoneEmpty("foo", "bar") = true
isAllBlank() 全是空白
public static boolean isAllBlank(final CharSequence... css)
所有串都是空白时返回true
StringUtils.isAllBlank(null) = true
StringUtils.isAllBlank(null, "foo") = false
StringUtils.isAllBlank(null, null) = true
StringUtils.isAllBlank("", "bar") = false
StringUtils.isAllBlank("bob", "") = false
StringUtils.isAllBlank(" bob ", null) = false
StringUtils.isAllBlank(" ", "bar") = false
StringUtils.isAllBlank("foo", "bar") = false
StringUtils.isAllBlank(new String[] {}) = true
isAnyBlank() 有任意一个是空白则true
public static boolean isAnyBlank(CharSequence... css)
StringUtils.isAnyBlank(null) = true
StringUtils.isAnyBlank(null, "foo") = true
StringUtils.isAnyBlank(null, null) = true
StringUtils.isAnyBlank("", "bar") = true
StringUtils.isAnyBlank("bob", "") = true
StringUtils.isAnyBlank(" bob ", null) = true
StringUtils.isAnyBlank(" ", "bar") = true
StringUtils.isAnyBlank("foo", "bar") = false
equalsIgnoreCase(a, b) 字符串是否相等
相等返回true,可传入null比较,不用怕空指针异常
join() 字符串拼接
public static String join(Object[] array, char separator)
字符串数组串接
StringUtils.join(null, *); // null
StringUtils.join([], *); // ""
StringUtils.join([null], *); // ""
StringUtils.join(["a", "b", "c"], ';'); // "a;b;c"
StringUtils.join(["a", "b", "c"], null); // "abc"
StringUtils.join([null, "", "a"], ';'); // ";;a"
List转逗号分隔字符串
String str = StringUtils.join(Arrays.asList("Milan", "London", "New York", "San Francisco"), ",");
split() 字符串分隔
逗号分隔字符串转List
利用Apache Commons的StringUtils
String str = "a,b,c";
List<String> result = Arrays.asList(StringUtils.split(str,","));
isNumeric() 判断是否数字
public static boolean isNumeric(CharSequence cs)
StringUtils.isNumeric(“1111”);
replace() 替换
public static String replace(final String text, final String searchString, final String replacement)
将 text 中的所有 searchString 替换为 replacement, 搜索时区分大小写
注意 text 本身不会被修改,替换后的传通过返回值返回。
public static String replace(final String text, final String searchString, final String replacement, int max)
max: 最多替换 max 个, max为-1时表示不限制即替换所有
StringUtils.replace(null, *, *) = null
StringUtils.replace("", *, *) = ""
StringUtils.replace("any", null, *) = "any"
StringUtils.replace("any", *, null) = "any"
StringUtils.replace("any", "", *) = "any"
StringUtils.replace("aba", "a", null) = "aba"
StringUtils.replace("aba", "a", "") = "b"
StringUtils.replace("aba", "a", "z") = "zbz"
replacePattern() 正则匹配替换
public static String replacePattern(final String source, final String regex, final String replacement)
String regex = "\\d{1,3}(\\.\\d{1,3}){3}"; // ipv4正则
String ret = StringUtils.replacePattern("http://192.167.1.1/image/001.jpg", regex, "127.0.0.1:8080");
removeStartIgnoreCase()从开头删除
StringUtils.removeStartIgnoreCase(null, *) = null
StringUtils.removeStartIgnoreCase("", *) = ""
StringUtils.removeStartIgnoreCase(*, null) = *
StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com"
StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com"
StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com"
StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
StringUtils.removeStartIgnoreCase("abc", "") = "abc"
例如
// 处理 host, 去掉开头的 www.
if (StringUtils.startsWithIgnoreCase(request.getHost(), "www.")) {
request.setHost(StringUtils.removeStartIgnoreCase(request.getHost(), "www."));
}
removeEndIgnoreCase() 从尾部删除
StringUtils.removeEndIgnoreCase(null, *) = null
StringUtils.removeEndIgnoreCase("", *) = ""
StringUtils.removeEndIgnoreCase(*, null) = *
StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com"
StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain"
StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
StringUtils.removeEndIgnoreCase("abc", "") = "abc"
StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
例如
// 文章 title 结尾
private static final String TITLE_SUFFIX = " | 小马的笔记";
// 处理 title, 去掉结尾的 | 小马的笔记
if (StringUtils.endsWithIgnoreCase(title, TITLE_SUFFIX)) {
title = StringUtils.removeEndIgnoreCase(title, TITLE_SUFFIX);
}
chop() 删除字符串最后一个字符
public static String chop(String str)
举例
StringUtils.chop(null) = null
StringUtils.chop("") = ""
StringUtils.chop("abc \r") = "abc "
StringUtils.chop("abc\n") = "abc"
StringUtils.chop("abc\r\n") = "abc"
StringUtils.chop("abc") = "ab"
StringUtils.chop("abc\nabc") = "abc\nab"
StringUtils.chop("a") = ""
StringUtils.chop("\r") = ""
StringUtils.chop("\n") = ""
StringUtils.chop("\r\n") = ""
left(str, len) 开头len长度子串
StringUtils.left(null, *) = null
StringUtils.left(*, -ve) = ""
StringUtils.left("", *) = ""
StringUtils.left("abc", 0) = ""
StringUtils.left("abc", 2) = "ab"
StringUtils.left("abc", 4) = "abc"
abbreviate() 缩写字符串
public static String abbreviate(final String str, final int maxWidth)
缩写字符串到指定长度
StringUtils.abbreviate(null, *) = null
StringUtils.abbreviate("", 4) = ""
StringUtils.abbreviate("abcdefg", 6) = "abc..."
StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
StringUtils.abbreviate("abcdefg", 4) = "a..."
StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
replaceChars() 多字符替换
一次性对应替换多个字符
StringUtils.replaceChars(null, *, *) = null
StringUtils.replaceChars("", *, *) = ""
StringUtils.replaceChars("abc", null, *) = "abc"
StringUtils.replaceChars("abc", "", *) = "abc"
StringUtils.replaceChars("abc", "b", null) = "ac"
StringUtils.replaceChars("abc", "b", "") = "ac"
StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya"
StringUtils.replaceChars("abcba", "bc", "y") = "ayya"
StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
将日期格式替换为只包含数字的字符串,不使用 replaceAll, String.replaceAll 会重复编译正则有性能问题
// 只留下数字,replaceAll("[\\D]", "") 重复编译正则有性能问题
String str = "2023-01-11 12:19:22";
System.out.println(StringUtils.replaceChars(str, "- :", ""));
replaceEach() 多字符串替换
一次性对应替换多个字符串
StringUtils.replaceEach(null, *, *) = null
StringUtils.replaceEach("", *, *) = ""
StringUtils.replaceEach("aba", null, null) = "aba"
StringUtils.replaceEach("aba", new String[0], null) = "aba"
StringUtils.replaceEach("aba", null, new String[0]) = "aba"
StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba"
StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b"
StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba"
StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
(example of how it does not repeat)
StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte"
ObjectUtils
allNotNull()全不是null
public static boolean allNotNull(Object... values)
所有值都不是 null 是返回 true
ObjectUtils.allNotNull(*) = true
ObjectUtils.allNotNull(*, *) = true
ObjectUtils.allNotNull(null) = false
ObjectUtils.allNotNull(null, null) = false
ObjectUtils.allNotNull(null, *) = false
ObjectUtils.allNotNull(*, null) = false
ObjectUtils.allNotNull(*, *, null, *) = false
NumberUtils
isParsable() 判断字符串是否十进制数字
无法解析 0x/0X开头的十六进制数、带e的科学计数法标识、以及 f/F/d/D/l/L 结尾的字符串数字
isCreatable() 判断字符串是否数字
可解析 0x/0X开头的十六进制数、0开头的八进制数、带e的科学计数法标识、以及 f/F/d/D/l/L 结尾的字符串数字
RandomUtils
nextInt()
RandomUtils.nextInt()
生成 0 到 Integer.MAX_VALUE 之间的随机整数RandomUtils.nextInt(0, 1000)
生成 0(包括) 到 1000(不包括) 之间的随机整数
public static int nextInt(final int startInclusive, final int endExclusive) {
Validate.isTrue(endExclusive >= startInclusive,
"Start value must be smaller or equal to end value.");
Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
if (startInclusive == endExclusive) {
return startInclusive;
}
return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
}
nextDouble()
RandomUtils.nextDouble(60, 100)
返回 60 到 100 左闭右开区间内的一个 double 随机数。
public static double nextDouble(final double startInclusive, final double endInclusive) {
Validate.isTrue(endInclusive >= startInclusive,
"Start value must be smaller or equal to end value.");
Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
if (startInclusive == endInclusive) {
return startInclusive;
}
return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextDouble());
}
RandomStringUtils
randomAlphabetic()随机字母
RandomStringUtils.randomAlphabetic(10)
返回长度为 10 的只包含字母的随机字符串
public static String randomAlphabetic(final int count) {
return random(count, true, false);
}
randomAlphanumeric()随机字母数字
RandomStringUtils.randomAlphanumeric(10)
返回长度为 10 的包含字母数字的随机字符串
public static String randomAlphanumeric(final int count) {
return random(count, true, true);
}
BeanUtils
http://commons.apache.org/proper/commons-beanutils/
依赖
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
describe()bean转map
Map<String, String> param = BeanUtils.describe(queryVO);
注意:对于 bean 中的 list 字段只能返回第一个值,不会自动给序列化为逗号分割
ExceptionUtils
getFullStackTrace() 获取异常堆栈
getRootCause() 获取根因异常
getRootCauseMessage 获取根因信息
ExceptionUtils.getRootCause(e).getMessage()
比如 jpa 报异常时嵌套了下面三层异常,在最底层的 MySQLSyntaxErrorException 异常信息中才能看到异常 sql 原因,此时就可以使用 getRootCause() 获取根因异常
javax.persistence.PersistenceException
org.hibernate.exception.SQLGrammarException
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException
Java 获取根因异常
public static Throwable findCauseUsingPlainJava(Throwable throwable) {
Objects.requireNonNull(throwable);
Throwable rootCause = throwable;
while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
rootCause = rootCause.getCause();
}
return rootCause;
}
How to Find an Exception’s Root Cause in Java
https://www.baeldung.com/java-exception-root-cause
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: