Apache-Commons-*
字符串
判断字符串是否为空白字符串
以前判断字符串是否为空:
if ((name == null) || (name.isEmpty())){}
应用 apache-common-lang3
的 StringUtils
:
void testIsBlank() { // true Assertions.assertTrue(StringUtils.isBlank(" ")); // true Assertions.assertTrue(StringUtils.isBlank("")); // true Assertions.assertTrue(StringUtils.isBlank(null)); // false Assertions.assertFalse(StringUtils.isBlank("foo")); // true Assertions.assertTrue(StringUtils.isAnyBlank(null, " ")); // false Assertions.assertFalse(StringUtils.isAnyBlank("foo", " bar "));}
右边填充字符串
有时候咱们须要生成流水号,例如4位数的流水号,从1
开始其余用字符'0'
填充,就能够应用 leftPad
办法,示例如下:
@Testvoid testLeftPad() { // 0001 Assertions.assertEquals("0001", StringUtils.leftPad("1", 4, '0'));}
左边填充字符串
@Testvoid testRightPad() { // 1000 Assertions.assertEquals("1000", StringUtils.rightPad("1", 4, '0'));}
宰割字符串
// ["a","b","c"]Assertions.assertEquals(Arrays.toString(new String[]{"a", "b", "c"}), Arrays.toString(StringUtils.split("a,b,c", ",")));
字符串比拟
// trueAssertions.assertTrue(StringUtils.equals(null, null));// falseAssertions.assertFalse(StringUtils.equals("null", null));
字符串已指定子字符串结尾
@Testvoid testStartWith() { // true Assertions.assertTrue(StringUtils.startsWith("hello,world", "hello")); // false Assertions.assertFalse(StringUtils.startsWith("你好,世界", "世界"));}
数值工具类
转换为 int 类型
将字符串转换为 int
类型,toInt(String str)
在转换失败的时候会返回默认值 0
,如果须要指定默认值那么能够应用 toInt(final String str, final int defaultValue)
:
@Testvoid testToInt() { // 0 Assertions.assertEquals(0, NumberUtils.toInt("abc")); // 0 Assertions.assertEquals(0, NumberUtils.toInt("01c")); // 0 Assertions.assertEquals(0, NumberUtils.toInt("1a3")); // 1 Assertions.assertEquals(1, NumberUtils.toInt("foo", 1)); // 11 Assertions.assertEquals(11, NumberUtils.toInt("11")); // 11 Assertions.assertEquals(11, NumberUtils.toInt("011", 3));}
数组
判断数组是否为空
@Testvoid testIsEmpty() { // true Assertions.assertTrue(ArrayUtils.isEmpty(new Object[]{})); // false Assertions.assertFalse(ArrayUtils.isEmpty(new String[]{"foo"}));}
日期
减少指定天数
除了减少指定的天数,common-lang3
还提供了:
addHours
:减少指定小时addMonths
:减少指定月数等...
@Testvoid testAddDay() {Date now = new Date();Date tomorrow = DateUtils.addDays(now, 1);Assertions.assertEquals(1, Duration.ofMillis(tomorrow.getTime() - now.getTime()).toDays());Assertions.assertEquals(Duration.ofDays(1).toMillis(), Duration.ofMillis(tomorrow.getTime() - now.getTime()).toMillis());}
格式化日期
tring pattern = "yyyy-MM-dd HH:mm:ss";Date d1 = DateUtils.parseDate("2022-10-22 00:00:00", pattern);Assertions.assertEquals("2022-10-22 00:00:00", DateFormatUtils.format(d1, pattern));
判断是否为同一天
String parsePattern = "yyyy-MM-dd HH:mm:ss";Date d1 = DateUtils.parseDate("2022-10-22 00:00:00", parsePattern);Date d2 = DateUtils.parseDate("2022-10-22 23:59:59", parsePattern);// trueAssertions.assertTrue(DateUtils.isSameDay(d1, d2));d1 = DateUtils.parseDate("2022-10-23 00:00:00", parsePattern);d2 = DateUtils.parseDate("2022-10-22 00:00:00", parsePattern);// falseAssertions.assertFalse(DateUtils.isSameDay(d1, d2));
枚举
@Testvoid testGetEnum() { Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> Season.valueOf("Spring")); // 默认返回null,不抛出异样 Assertions.assertNull(EnumUtils.getEnum(Season.class, "spring")); // 指定默认值 Assertions.assertEquals(Season.SPRING, EnumUtils.getEnumIgnoreCase(Season.class, "spring")); // 疏忽大小写匹配 Assertions.assertEquals(Season.SPRING, EnumUtils.getEnum(Season.class, "spring", Season.SPRING));}enum Season { SPRING,}
Guava
宰割字符串
在理解 Guava
提供的字符串分割器之前,咱们先来看看 Java
提供的字符串分隔有什么毛病,如下所示,输入的后果为:
",a,,b,".split(",")
"", "a", "", "b", ""
null, "a", null, "b", null
"a", null, "b"
"a", "b"
- 以上都不对
正确输入后果是 [, a, , b]
,答案是选项5:“以上都不对”。Splitter
不仅实现了字符串分隔,还提供了对应的修饰符,即对拆分后果进行解决,例如:
String str = "foo, bar ,,,baz";// ["foo","bar","baz"]Splitter.on(",") .trimResults() .omitEmptyStrings() .splitToList(str);// [高低高低左, 左, 右右]str = "baba高低高低左a左b右右";res = Splitter.on(CharMatcher.inRange('a', 'b')) .trimResults() .omitEmptyStrings() .splitToList(str);// [高低高低左, 左, 右右] log.info("{}", res);
拆分器工厂
办法 | 形容 | 示例 |
---|---|---|
Splitter.on(char) | 按单个字符拆分 | Splitter.on(','); |
Splitter.on(CharMatcher) | 按字符匹配器拆分 | Splitter.on(CharMatcher.inRange('a', 'b')) |
Splitter.on(String) | 按字符串拆分 | Splitter.on(", ") |
Splitter.on(Pattern)或onPattern(String) | 按正则表达式拆分 | Splitter.on("\r?\n ") |
Splitter.fixedLength(int) | 按固定长度拆分;最初一段可能比给定长度短,但不会为空。 | Splitter.fixedLength(3) |
拆分器修饰符
办法 | 形容 |
---|---|
omitEmptyStrings() | 从后果中主动疏忽空白字符串 |
trimResults() | 移除后果字符串的首位空白字符 |
trimResults(CharMatcher) | 给定匹配器,移除后果字符串的首位匹配字符 |
limit(int) | 限度拆分出的字符串数量 |
不可变汇合
public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of( "red", "orange", "yellow", "green", "blue", "purple");class Foo { Set<Bar> bars; Foo(Set<Bar> bars) { this.bars = ImmutableSet.copyOf(bars); // defensive copy! }}
不可变对象有很多的长处:
- 当对象被不可信的库调用时,不可变模式是平安的;
- 不可变对象被多个线程调用时,不存在竞态条件问题
- 不可变汇合不须要思考变动,因而能够节省时间和空间。所有不可变的汇合都比它们的可变模式有更好的内存利用率(剖析和测试细节);
- 不可变对象因为有固定不变,能够作为常量来平安应用。
应用不可变汇合
不可变汇合能够用如下多种形式创立:
copyOf
:ImmutableList.copyOf
of
:ImmutableList.of("a","b","c")
Builder
工具,例如:
public static final ImmutableSet<Color> GOOGLE_COLORS = ImmutableSet.<Color>builder() .addAll(WEBSAFE_COLORS) .add(new Color(0, 191, 255)) .build();
连贯字符串
@Testvoid testJoin() { // foo,bar Assertions.assertEquals("foo,bar", Joiner.on(',').join(ImmutableList.of("foo", "bar"))); // foo Assertions.assertEquals("foo", Joiner.on(',').skipNulls().join("foo", null)); // foo,empty Assertions.assertEquals("foo,empty", Joiner.on(',').useForNull("empty").join("foo", null)); // 抛出空指针异样 Assertions.assertThrowsExactly(NullPointerException.class, () -> Joiner.on(',').join("foo", null));}
正告:joiner实例总是不可变的。用来定义joiner指标语义的配置办法总会返回一个新的joiner实例。这使得joiner实例都是线程平安的,你能够将其定义为static final常量。
Strings
将 null
转换为空字符串:
Assertions.assertEquals("", Strings.nullToEmpty(null));
将空字符串转换为 null
:
Assertions.assertEquals(null, Strings.emptyToNull(""));Assertions.assertEquals(null, Strings.emptyToNull(null));
CharMatcher
String noControl = CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); //移除control字符String theDigits = CharMatcher.DIGIT.retainFrom(string); //只保留数字字符String spaced = CharMatcher.WHITESPACE.trimAndCollapseFrom(string, ' ');//去除两端的空格,并把两头的间断空格替换成单个空格String noDigits = CharMatcher.JAVA_DIGIT.replaceFrom(string, "*"); //用*号替换所有数字String lowerAndDigit = CharMatcher.JAVA_DIGIT.or(CharMatcher.JAVA_LOWER_CASE).retainFrom(string);// 只保留数字和小写字母
Spring
判断汇合是否为空
@Testvoid testIsEmpty() { Assertions.assertTrue(CollectionUtils.isEmpty((List<?>) null)); Assertions.assertTrue(CollectionUtils.isEmpty((Set<?>) null)); Assertions.assertTrue(CollectionUtils.isEmpty((Map<?, ?>) null)); Assertions.assertTrue(CollectionUtils.isEmpty(Collections.emptyList())); Assertions.assertTrue(CollectionUtils.isEmpty(Collections.emptySet())); Assertions.assertTrue(CollectionUtils.isEmpty(Collections.emptyMap())); Assertions.assertTrue(CollectionUtils.isEmpty(List.of())); Assertions.assertTrue(CollectionUtils.isEmpty(Set.of())); Assertions.assertTrue(CollectionUtils.isEmpty(Map.of())); List<Object> list = new LinkedList<>(); list.add(new Object()); Assertions.assertFalse(CollectionUtils.isEmpty(list)); Assertions.assertFalse(CollectionUtils.isEmpty(List.of("foo"))); Map<String, String> map = new HashMap<>(); map.put("foo", "bar"); Assertions.assertFalse(CollectionUtils.isEmpty(map)); Assertions.assertFalse(CollectionUtils.isEmpty(Map.of("foo", "bar")));}
获取汇合的第一个元素
@Testvoid testFirstElement() { Assertions.assertNull(CollectionUtils.firstElement((Set<?>) null)); Assertions.assertNull(CollectionUtils.firstElement((List<?>) null)); List<String> list = new ArrayList<>(); list.add(null); // null Assertions.assertNull(CollectionUtils.firstElement(list)); list = new ArrayList<>(); list.add("foo"); // foo Assertions.assertEquals("foo", CollectionUtils.firstElement(list)); list = List.of("foo", "bar"); // foo Assertions.assertEquals("foo", CollectionUtils.firstElement(list)); Set<String> set = new TreeSet<>(); set.add("b"); set.add("a"); // a Assertions.assertEquals("a", CollectionUtils.firstElement(set)); // b set = new TreeSet<>(Comparator.reverseOrder()); set.add("b"); set.add("a"); Assertions.assertEquals("b", CollectionUtils.firstElement(set));}
获取汇合的最初一个元素
@Testvoid testLastElement() { Assertions.assertNull(CollectionUtils.lastElement((Set<?>) null)); Assertions.assertNull(CollectionUtils.lastElement((List<?>) null)); List<String> list = new ArrayList<>(); list.add(null); Assertions.assertNull(CollectionUtils.lastElement(list)); list = new ArrayList<>(); list.add("foo"); list.add("bar"); // bar Assertions.assertEquals("bar", CollectionUtils.lastElement(list)); list = List.of("foo", "bar"); Assertions.assertEquals("bar", CollectionUtils.lastElement(list)); Set<String> set = new TreeSet<>(); set.add("b"); set.add("a"); // b Assertions.assertEquals("b", CollectionUtils.lastElement(set)); set = new TreeSet<>(Comparator.reverseOrder()); set.add("b"); set.add("a"); // a Assertions.assertEquals("a", CollectionUtils.lastElement(set));}
对象属性拷贝
增加一个测试对象:
class User { private String name; private String email; // 疏忽getXxx和setXxx办法
@Testvoid testCopyProperties() { User user = new User(); user.setName("foo"); user.setEmail("bar"); User target = new User(); // 拷贝属性 BeanUtils.copyProperties(user, target, "email"); Assertions.assertEquals("foo", target.getName()); Assertions.assertNull(target.getEmail());}
命名的 ThreadLocal
@Testvoid testNamedThreadLocal() { NamedThreadLocal<String> threadLocal = new NamedThreadLocal<>("task"); Assertions.assertEquals("task", threadLocal.toString());}
判断对象是否相等
@Testvoid testNullSafeEquals() { Assertions.assertTrue(ObjectUtils.nullSafeEquals(null, null)); Assertions.assertTrue(ObjectUtils.nullSafeEquals("a", "a")); Assertions.assertTrue(ObjectUtils.nullSafeEquals(Optional.of("a"), Optional.of("a")));}
判断对象是否为空
@Testvoid testIsEmpty() { Assertions.assertTrue(ObjectUtils.isEmpty((Object) null)); Assertions.assertTrue(ObjectUtils.isEmpty(Optional.empty())); Assertions.assertTrue(ObjectUtils.isEmpty("")); Assertions.assertTrue(ObjectUtils.isEmpty(new String[]{})); Assertions.assertTrue(ObjectUtils.isEmpty(Collections.emptyList())); Assertions.assertTrue(ObjectUtils.isEmpty(Collections.emptyMap()));}
资源工具类
有时候咱们须要加载 classpath
目录下的资源,例如:
File file = new File(ResourceUtilsTests.class.getClassLoader().getResource("log4j2.xml").toURI());Assertions.assertEquals("log4j2.xml", file.getName());
应用 Spring
的 ResourceUtils
只须要这么写:
File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "log4j2.xml");Assertions.assertEquals("log4j2.xml", file.getName());
计时器
@Testvoid testStopWatch() throws InterruptedException { // 创立一个计时器(秒表) StopWatch stopWatch = new StopWatch(); // 开始计时 stopWatch.start(); Thread.sleep(Duration.ofSeconds(1).toMillis()); // 进行计时 stopWatch.stop(); // 获取总耗时(毫秒) // 1005ms. log.info("{}ms.", stopWatch.getTotalTimeMillis()); // 1s. log.info("{}s.", Duration.ofMillis(stopWatch.getTotalTimeMillis()).toSeconds());}
UriComponentsBuilder
有时候咱们须要在服务端手动发送申请,在申请 url
咱们应用字符串拼接的形式,Spring
提供了UriComponentsBuilder
能让咱们更加语意化来构建一个申请url
,而且还会主动对url
进行编码:
@Testvoid testFromUriString() { String uri = UriComponentsBuilder .fromUriString("/coffee/{foo}/{id}/like") .build("aa", "bb") .toString(); Assertions.assertEquals("/coffee/aa/bb/like", uri); uri = UriComponentsBuilder .fromUriString("http://localhost:8080/coffe/{id}") .encode() .build(1).toString(); Assertions.assertEquals("http://localhost:8080/coffe/1", uri); uri = UriComponentsBuilder .fromUriString("http://localhost:8080/coffee?name={name}") .build(" ").toString(); Assertions.assertEquals("http://localhost:8080/coffee?name=%20",uri);}
hutool
校验
@Testvoid testIsCitizenId() { // 校验是否为身份证 Assertions.assertTrue(Validator.isCitizenId("110101199003074477")); // 15位身份证号码验证 Assertions.assertTrue(Validator.isCitizenId("410001910101123")); // 10位身份证号码验证 Assertions.assertTrue(Validator.isCitizenId("U193683453"));}@Testvoid testIsMobile() { // 校验是否为手机号 Assertions.assertTrue(Validator.isMobile("13900221432")); Assertions.assertTrue(Validator.isMobile("015100221432")); Assertions.assertTrue(Validator.isMobile("+8618600221432"));}@Testvoid testIsPlateNumber() { // 校验是否为车牌号 Assertions.assertTrue(Validator.isPlateNumber("粤BA03205")); Assertions.assertTrue(Validator.isPlateNumber("闽20401领"));}
emoji
@Testvoid testToUnicode() { String unicode = EmojiUtil.toUnicode(":smile:"); Assertions.assertEquals("", unicode);}@Testvoid testToAlias() { Assertions.assertEquals(":smile:", EmojiUtil.toAlias(""));}@Testvoid testToHtml() { String html = EmojiUtil.toHtml(""); Assertions.assertEquals("😄", html);}
拼音
引入依赖:
<dependency> <groupId>io.github.biezhi</groupId> <artifactId>TinyPinyin</artifactId> <version>2.0.3.RELEASE</version></dependency>
获取拼音:
@Testvoid testGetPinyin() { Assertions.assertEquals("ceng", PinyinUtil.getPinyin("曾")); Assertions.assertEquals("f o o", PinyinUtil.getPinyin("foo")); Assertions.assertThrowsExactly(NullPointerException.class, () -> PinyinUtil.getPinyin(null)); Assertions.assertEquals(" ", PinyinUtil.getPinyin(" ")); // ? ? log.info("{}", PinyinUtil.getPinyin("")); Assertions.assertEquals("! # ¥ % ( # ) @", PinyinUtil.getPinyin("!#¥%(#)@"));}
压缩
转换
@Testvoid testDigitToChinese() { Assertions.assertEquals("零元零壹分",Convert.digitToChinese(0.01));}
二维码
@Testvoid testGenerate() { // 生成二维码 final BufferedImage image = QrCodeUtil.generate("https://hutool.cn/", 300, 300); Assertions.assertNotNull(image);}
SpringUtil
SpringUtil
实现了通过 @EnalbeAutoConfiguuration
主动拆卸 Bean
,文件 spring.factories
定义如下:
# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\cn.hutool.extra.spring.SpringUtil
// 获取beanfinal Demo2 testDemo = SpringUtil.getBean("testDemo");
版本比拟
@Testvoid testCompare() { Assertions.assertEquals(-1, VersionComparator.INSTANCE.compare("1.12.1", "1.12.1c")); Assertions.assertEquals(1, VersionComparator.INSTANCE.compare("V0.0.20170102", "V0.0.20170101"));}
身份证
private static final String ID_18 = "321083197812162119";private static final String ID_15 = "150102880730303";/** * 依据身份编号获取生日,只反对15或18位身份证号码. */@Testvoid testGetBirthByIdCard() { Assertions.assertEquals(IdcardUtil.getBirthByIdCard(ID_18), "19781216"); Assertions.assertEquals(IdcardUtil.getBirthByIdCard(ID_15), "19880730");}
打码/信息脱敏
void testIdCardNum() { Assertions.assertEquals("5***************1X", DesensitizedUtil.idCardNum("51343620000320711X", 1, 2));}@Testvoid testMobilePhone() { Assertions.assertEquals("180****1999", DesensitizedUtil.mobilePhone("18049531999"));}@Testvoid testPassword() { Assertions.assertEquals("**********", DesensitizedUtil.password("1234567890"));}@Testvoid testEmail() { Assertions.assertEquals("d********@126.com", DesensitizedUtil.email("duandazhi@126.com")); Assertions.assertEquals("d********@gmail.com.cn", DesensitizedUtil.email("duandazhi@gmail.com.cn")); Assertions.assertEquals("d*************@gmail.com.cn", DesensitizedUtil.email("duandazhi-jack@gmail.com.cn"));}
加密
引入依赖:
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.69</version></dependency>
SM4 对称加密:
String content = "test中文"; SymmetricCrypto sm4 = SmUtil.sm4(); String encryptHex = sm4.encryptHex(content); String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
JDK
Collections
返回空数组:
@Testvoid testEmptyList() { Assertions.assertTrue(Collections.emptyList().isEmpty());}
Arrays
打印数组信息,不便debug:
@Testvoid testToString() { Assertions.assertEquals("[a, b, c]",Arrays.toString(new String[]{"a","b","c"})); Assertions.assertEquals("null",Arrays.toString((String[]) null));}
Duration
有时候咱们传递一些工夫参数,单位可能是秒、毫米、分钟、小时等,例如线程睡眠工夫,咱们能够应用 Duration
来语意化咱们的代码:
@Testvoid test() throws InterruptedException { Thread.currentThread().sleep(Duration.ofSeconds(1).toMillis());}
StandardCharsets
咱们有时候须要用到字符集,例如:
URLEncoder
InputStreamReader
IOUtils.toString
能够应用 StandardCharsets
,例如:
IOUtils.toString(new ClassPathResource("log4j2.xml").getInputStream(), StandardCharsets.UTF_8)
Objects
对象 equals
:
@Testvoid testEquals() { Assertions.assertTrue(Objects.equals(null, null)); Assertions.assertFalse(Objects.equals("a", "b"));}
防止空指针获取 hashCode
:
@Testvoid testHashCode() { Assertions.assertEquals(0, Objects.hashCode(null)); Assertions.assertEquals("a".hashCode(), Objects.hashCode("a"));}
null
转默认值:
@Testvoid testRequireNonNullElse() { Assertions.assertEquals("a", Objects.requireNonNullElse(null, "a"));}
判断对象不为空,配合 Stream
:
@Testvoid testNonNull() { List<String> names = Lists.newArrayList("foo", null); names = names.stream() .filter(Objects::nonNull) .collect(Collectors.toList()); Assertions.assertEquals(names, List.of("foo"));}
Optional
@Testvoid testOptional() { // 创立一个 Optional 对象,不容许为空 Optional<String> optional = Optional.of("a"); // 获取值,如果值为空抛出 NoSuchElementException 异样 Assertions.assertEquals("a", optional.get()); // 判断Optional的值是否为空 Assertions.assertFalse(optional.isEmpty()); // 判断Optional的值是否不为空 Assertions.assertTrue(optional.isPresent()); // 创立一个 Optional 对象,容许为 null optional = Optional.ofNullable(null); // 获取值,如果值为空抛出 NoSuchElementException 异样 Assertions.assertThrowsExactly(NoSuchElementException.class, optional::get); // 判断Optional的值是否为空 Assertions.assertTrue(optional.isEmpty()); // 判断Optional的值是否不为空 Assertions.assertFalse(optional.isPresent()); // 创立一个空的Optional对象 optional = Optional.empty(); // 获取值,如果值为空抛出 NoSuchElementException 异样 Assertions.assertThrowsExactly(NoSuchElementException.class, optional::get); // 判断Optional的值是否为空 Assertions.assertTrue(optional.isEmpty()); // 判断Optional的值是否不为空 Assertions.assertFalse(optional.isPresent());}