19【hutool】hutool-core

625 阅读19分钟

该系列文章主要是对 hutool 工具类的介绍,详情可以参考

hutool.cn/docs

19 hutool-core

封装了一些通用的工具类,是整个 hutool 工具包的核心

注解工具 - AnnotationUtil

    @Test
    public void testGetAnnotation() {
        MyAnnotation annotation = AnnotationUtil.getAnnotation(ClassWithAnnotation.class, MyAnnotation.class);
        Console.log(annotation.value());
    }

    @Test
    public void getAnnotationValue() {
        Object value = AnnotationUtil.getAnnotationValue(ClassWithAnnotation.class, MyAnnotation.class);
        Console.log(value);
    }

Bean工具 - BeanUtil

把一个拥有对属性进行set和get方法的类,我们就可以称之为JavaBean。

Bean工具类主要是针对这些setXXX和getXXX方法进行操作,比如将Bean对象转为Map等等。

    @Test
    public void isBean() {
        // 根据是否存在只有一个参数的setXXX方法或者public类型的字段来判定是否是一个Bean对象
        boolean isBean = BeanUtil.isBean(HashMap.class);
        Console.log(isBean);
    }

    @Test
    public void fillBean() {
        final Person person = BeanUtil.fillBean(new Person(), new ValueProvider<String>() {

            @Override
            public Object value(final String key, final Type valueType) {
                switch (key) {
                    case "name":
                        return "张三";
                    case "age":
                        return 18;
                }
                return null;
            }

            @Override
            public boolean containsKey(final String key) {
                // 总是存在key
                return true;
            }

        }, CopyOptions.create());

        Console.log(person);
    }

    @Test
    public void mapToBeanIgnoreCaseTest() {
        final HashMap<String, Object> map = MapUtil.newHashMap();
        map.put("Name", "Joe");
        map.put("aGe", 12);

        final Person person = BeanUtil.fillBeanWithMapIgnoreCase(map, new Person(), false);
        Console.log(person);
    }

    @Test
    public void toMap() {
        final Person person = new Person();
        person.setAge(14);
        person.setOpenid("11213232");
        person.setName("测试A11");

        final Map<?, ?> map = BeanUtil.beanToMap(person);
        Console.log(map);
    }
    
    @Test
    public void dynaBeanTest() {
        Person person = new Person();
        // 像操作 map 一样动态操作 Bean
        DynaBean bean = DynaBean.create(person);
        bean.set("name", "李华");
        bean.set("age", 12);

        String name = bean.get("name");
        Assert.assertEquals(person.getName(), name);
        int age = bean.get("age");
        Assert.assertEquals(person.getAge(), age);

        //执行指定方法
        Object invoke = bean.invoke("testMethod");
        Console.log(invoke);
    }
    

支持泛型的克隆接口和克隆类

  • 引用拷贝 创建一个指向对象的引用变量的拷贝。地址一样,引用改变了。

  • 对象拷贝 重新开辟一块地址空间。以下提的深拷贝和浅拷贝都是对象拷贝

  • 深拷贝 会对对象里的对象进行拷贝

  • 浅拷贝 不会对对象里的对象进行拷贝

    @Test
    public void cloneTest() throws Exception {
        Cat cat1 = new Cat();
        Cat cat2 = (Cat) cat1.clone();
        Console.log("cat1:{}", cat1);
        Console.log("cat2:{}", cat2);

        Dog dog1 = new Dog();
        Dog dog2 = dog1.clone();

        Console.log("dog1:{}", dog1);
        Console.log("dog2:{}", dog2);
    }

    @Test
    public void cloneTestV2() {
        Car car1 = new Car();
        Car car2 = car1.clone();
        Console.log("car1:{}", car1);
        Console.log("car2:{}", car2);
    }

Cat 实现 jdk 的 Cloneable 接口

public class Cat implements Cloneable {

    private String name;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Dog 实现hutool 的 Cloneable 接口,强制实现 clone 方法

public class Dog implements Cloneable<Dog> {
    @Override
    public Dog clone() {
        try {
            return (Dog) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new CloneRuntimeException(e);
        }
    }
}

Car 继承 CloneSupport 类,有默认的 clone 方法实现

public class Car extends CloneSupport<Car> {

    private String name;
}

Codec编码

Base62

短链接生成

Base64

Base64编码是用64(2的6次方)个ASCII字符来表示256(2的8次方)个ASCII字符,也就是三位二进制数组经过编码后变为四位的ASCII字符显示,长度比原来增加1/3。

莫尔斯电码-Morse

摩尔斯电码也被称作摩斯密码,是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母、数字和标点符号。

摩尔斯电码是由点dot(.)划dash(-)这两种符号所组成的。

BCD码

BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。

回转N位密码-Rot

RotN(rotate by N places),回转N位密码,是一种简易的替换式密码,也是过去在古罗马开发的凯撒加密的一种变体。

    @Test
    public void base62() {
        String a = "www.baidu.com";
        String encode = Base62.encode(a);
        Console.log(encode);
        String decodeStr = Base62.decodeStr(encode);
        Console.log(decodeStr);
    }

    @Test
    public void base64() {
        String a = "hello world";
        String encode = Base64.encode(a);
        Console.log(encode);
        String decodeStr = Base64.decodeStr(encode);
        Console.log(decodeStr);
    }

    @Test
    public void morse() {
        Morse morseCoder = new Morse();
        String text = "Hello World!";
        String encode = morseCoder.encode(text);
        Console.log(encode);
        String decodeStr = morseCoder.decode(encode);
        Console.log(decodeStr);
    }

    @Test
    public void bcd() {
        String text = "123456ABCDEF";
        //转BCD
        byte[] bcd = BCD.strToBcd(text);
        Console.log(new String(bcd, StandardCharsets.UTF_8));
        //解码BCD
        String str = BCD.bcdToStr(bcd);
        Console.log(str);
    }

    @Test
    public void rot() {
        String str = "1f2e9df6131b480b9fdddc633cf24996";
        String encode13 = Rot.encode13(str);
        Console.log(encode13);
        String decode13 = Rot.decode13(encode13);
        Console.log(decode13);
    }

集合工具

操作集合类的方法,许多方法都是通过 stream 流来实现的,对于习惯用 stream 流来排序,过滤的开发者,没必要强制使用工具类

    @Test
    public void newArrayListTest() {
        ArrayList<String> list = CollUtil.newArrayList("a", "b", "c");
        for (String str : list) {
            Console.log(str);
        }
    }

    @Test
    public void joinTest() {
        String[] col = new String[]{"a", "b", "c", "d", "e"};
        List<String> colList = CollUtil.newArrayList(col);
        String str = CollUtil.join(colList, "#");
        // a#b#c#d#e
        Console.log(str);
    }

    @Test
    public void sortPageAllTest() {
        // 新建三个列表,CollUtil.newArrayList方法表示新建ArrayList并填充元素
        List<Integer> list1 = CollUtil.newArrayList(1, 2, 3);
        List<Integer> list2 = CollUtil.newArrayList(4, 5, 6);
        List<Integer> list3 = CollUtil.newArrayList(7, 8, 9);

        // 参数表示把list1,list2,list3合并并按照从小到大排序后,取0~2个(包括第0个,不包括第2个),结果是[1,2]
        List<Integer> result = CollUtil.sortPageAll(0, 10, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        }, list1, list2, list3);
        // 合并 + 排序 + 分页
        for (Integer integer : result) {
            Console.log(integer);
        }
    }

    @Test
    public void removeWithAddIfTest() {
        ArrayList<Integer> list = CollUtil.newArrayList(1, 2, 3);
        // 过滤条件,ele == 1
        List<Integer> resultList = CollUtil.removeWithAddIf(list, ele -> 1 == ele);
        // 过滤删除了 1 ,[2,3]
        Console.log(list);
        // 过滤的数组, [1]
        Console.log(resultList);

        // 也可以将返回的数组当参数传入
        list = CollUtil.newArrayList(1, 2, 3);
        resultList = new ArrayList<>();
        CollUtil.removeWithAddIf(list, resultList, ele -> 2 == ele);
        // 过滤删除了 2 ,[1,3]
        Console.log(list);
        // 过滤的数组, [2]
        Console.log(resultList);
    }

    @Test
    public void padTest() {
        List<String> srcList = CollUtil.newArrayList();
        // 左边补 b,直到长度为 1
        CollUtil.padLeft(srcList, 1, "b");
        // 左边补 a,直到长度为 2
        CollUtil.padLeft(srcList, 2, "a");
        // [a,b]
        Console.log(srcList);
        // 左边补 a,直到长度为 4
        CollUtil.padLeft(srcList, 4, "a");
        // [a,a,a,b]
        Console.log(srcList);
        // 右边补 c,直到长度为 10
        CollUtil.padRight(srcList, 10, "c");
        // [a, a, a, b, c, c, c, c, c, c]
        Console.log(srcList);
    }

    @Test
    public void unionTest() {
        ArrayList<String> list1 = CollUtil.newArrayList("a", "b", "b", "c", "d", "x");
        ArrayList<String> list2 = CollUtil.newArrayList("a", "b", "b", "b", "c", "d");
        // 取交集
        Collection<String> union = CollUtil.union(list1, list2);
        // [a, b, b, b, c, d, x]
        Console.log(union);
    }

    @Test
    public void intersectionTest() {
        ArrayList<String> list1 = CollUtil.newArrayList("a", "b", "b", "c", "d", "x");
        ArrayList<String> list2 = CollUtil.newArrayList("a", "b", "b", "b", "c", "d");
        // 取并集
        Collection<String> intersection = CollUtil.intersection(list1, list2);
        // [a, b, b, c, d]
        Console.log(intersection);
    }

    @Test
    public void intersectionDistinctTest() {
        ArrayList<String> list1 = CollUtil.newArrayList("a", "b", "b", "c", "d", "x");
        ArrayList<String> list2 = CollUtil.newArrayList("a", "b", "b", "b", "c", "d");
        // 取并集并去重
        Collection<String> intersectionDistinct = CollUtil.intersectionDistinct(list1, list2);
        // [a, b, c, d]
        Console.log(intersectionDistinct);
    }

    @Test
    public void subtractTest() {
        ArrayList<String> list1 = CollUtil.newArrayList("a", "b", "b", "c", "d", "x");
        ArrayList<String> list2 = CollUtil.newArrayList("a", "b", "b", "b", "c", "d", "x2");
        // 取差集,在 1 不在 2
        Collection<String> subtract = CollUtil.subtract(list1, list2);
        // [x]
        Console.log(subtract);
        // 取差集,在 2 不在 1
        Collection<String> subtract2 = CollUtil.subtract(list2, list1);
        // [x2]
        Console.log(subtract2);
    }
    
    @Test
    public void testToList() {
        ArrayList<String> list = ListUtil.toList("a", "b", "c");
        Console.log(list);
    }

    @Test
    public void testIndexOfAll() {
        List<String> list = ListUtil.toList("1", "2", "3", "2", "3", "2", "3");
        int[] index = ListUtil.indexOfAll(list, (str) -> {
            return "2".equals(str);
        });
        Console.log(index);
    }
    
    

比较器

在JDK提供的比较器中,对于null的比较没有考虑,Hutool封装了相关比较,可选null是按照最大值还是最小值对待。

    @Test
    public void compareTest() {
        int compare = CompareUtil.compare(null, "a", true);
        Console.log(compare > 0);
        compare = CompareUtil.compare(null, "a", false);
        Console.log(compare < 0);
    }

    @Test
    public void comparingPinyin() {
        List<String> list = ListUtil.toList("成都", "北京", "上海", "深圳");

        List<String> ascendingOrderResult = ListUtil.of("北京", "成都", "上海", "深圳");
        List<String> descendingOrderResult = ListUtil.of("深圳", "上海", "成都", "北京");
        // 正序
        list.sort(CompareUtil.comparingPinyin(e -> e));
        // ["北京", "成都", "上海", "深圳"]
        Console.log(list, ascendingOrderResult);
        // 反序
        list.sort(CompareUtil.comparingPinyin(e -> e, true));
        // ["深圳", "上海", "成都", "北京"]
        Console.log(list, descendingOrderResult);
    }

类型转换

    @Test
    public void toStrTest() {
        int a = 1;
        long[] b = {1, 2, 3, 4, 5};
        String aStr = Convert.toStr(a);
        // 1
        Console.log(aStr);
        String bStr = Convert.toStr(b);
        // [1, 2, 3, 4, 5]
        Console.log(Convert.toStr(bStr));
    }

    @Test
    public void toIntTest() {
        String a = " 34232";
        Integer aInteger = Convert.toInt(a);
        // 34232
        Console.log(aInteger);

        // 带小数测试
        String b = " 34232.00";
        Integer bInteger = Convert.toInt(b);
        // 34232
        Console.log(bInteger);

        // boolean测试
        boolean c = true;
        Integer cInteger = Convert.toInt(c);
        // 1
        Console.log(cInteger);

        // str测试
        String d = "08";
        Integer dInteger = Convert.toInt(d);
        // 8
        Console.log(dInteger);
    }

    @Test
    public void toDateTest() {
        Date date = Convert.toDate("2022-10-25");
        Console.log(date);
    }

    @Test
    public void toListTest() {
        List<String> list = Arrays.asList("1", "2");
        String str = Convert.toStr(list);
        // [1,2]
        Console.log(str);
        List<String> list2 = Convert.toList(String.class, str);
        // [1,2]
        Console.log(list2);
        List<Integer> list3 = Convert.toList(Integer.class, str);
        // [1,2]
        Console.log(list3);
    }

    @Test
    public void toListTest2() {
        Object[] a = {"a", "你", "好", "", 1};
        List<String> list = Convert.convert(new TypeReference<List<String>>() {
        }, a);
        // [a, 你, 好, , 1]
        Console.log(list);
    }

    @Test
    public void hexTest() {
        String a = "hello world";
        String hex = Convert.toHex(a, CharsetUtil.CHARSET_UTF_8);
        Console.log(hex);
        String raw = Convert.hexToStr(hex, CharsetUtil.CHARSET_UTF_8);
        Console.log(raw);
    }

    @Test
    public void unicodeTest() {
        String a = "hello world";
        String unicode = Convert.strToUnicode(a);
        Console.log(unicode);
        String raw = Convert.unicodeToStr(unicode);
        Console.log(raw);

        // 针对有特殊空白符的Unicode
        String str = "你 好";
        String unicode2 = Convert.strToUnicode(str);
        Console.log(unicode2);

        String str2 = Convert.unicodeToStr(unicode2);
        Console.log(str2);
    }

    @Test
    public void convertCharsetTest() {
        String a = "我不是乱码";
        // 转换后result为乱码
        String result = Convert.convertCharset(a, CharsetUtil.UTF_8, CharsetUtil.ISO_8859_1);
        Console.log(result);
        String raw = Convert.convertCharset(result, CharsetUtil.ISO_8859_1, "UTF-8");
        Console.log(raw);
        Assert.assertEquals(raw, a);
    }

日期时间

    @Test
    public void nowTest() {
        // 当前时间
        final Date date = DateUtil.date();
        Console.log(date);
        // 当前时间
        final Date date2 = DateUtil.date(Calendar.getInstance());
        Console.log(date2);
        // 当前时间
        final Date date3 = DateUtil.date(System.currentTimeMillis());
        Console.log(date3);

        // 当前日期字符串,格式:yyyy-MM-dd HH:mm:ss
        final String now = DateUtil.now();
        Console.log(now);
        // 当前日期字符串,格式:yyyy-MM-dd
        final String today = DateUtil.today();
        Console.log(today);
    }

    @Test
    public void formatAndParseTest() {
        final String dateStr = "2022-10-25";
        final Date date = DateUtil.parse(dateStr);

        final String format = DateUtil.format(date, "yyyy/MM/dd");
        Console.log(format);

        // 常用格式的格式化
        final String formatDate = DateUtil.formatDate(date);
        Console.log(formatDate);
        final String formatDateTime = DateUtil.formatDateTime(date);
        Console.log(formatDateTime);
        final String formatTime = DateUtil.formatTime(date);
        Console.log(formatTime);
    }

    @Test
    public void beginAndEndTest() {
        final Date date = DateUtil.date();
        // 一天的开始
        final Date beginOfDay = DateUtil.beginOfDay(date);
        Console.log(beginOfDay);
        // 一天的结束
        final Date endOfDay = DateUtil.endOfDay(date);
        Console.log(endOfDay);
    }

    @Test
    public void offsetDateTest() {
        final Date date = DateUtil.date();
        Console.log(date);

        // 偏移天
        final Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 2);
        Console.log(newDate);

        // 偏移天
        final DateTime newDate2 = DateUtil.offsetDay(date, 3);
        Console.log(newDate2);

        // 偏移小时
        final DateTime newDate3 = DateUtil.offsetHour(date, -3);
        Console.log(newDate3);

        // 偏移月
        final DateTime offsetMonth = DateUtil.offsetMonth(date, -1);
        Console.log(offsetMonth);
    }

    @Test
    public void betweenTest() {
        final String dateStr1 = "2017-03-01 22:34:23";
        final Date date1 = DateUtil.parse(dateStr1);

        final String dateStr2 = "2017-04-01 23:56:14";
        final Date date2 = DateUtil.parse(dateStr2);

        //相差一个月,31天
        long betweenDay = DateUtil.between(date1, date2, DateUnit.DAY);
        Console.log(betweenDay);
    }

    @Test
    public void formatBetweenTest() {
        final String dateStr1 = "2017-03-01 22:34:23";
        final Date date1 = DateUtil.parse(dateStr1);

        final String dateStr2 = "2017-04-01 23:56:14";
        final Date date2 = DateUtil.parse(dateStr2);

        final long between = DateUtil.between(date1, date2, DateUnit.MS);
        Console.log(between);
        final String formatBetween = DateUtil.formatBetween(between, BetweenFormatter.Level.MINUTE);
        Console.log(formatBetween);
    }

    @Test
    public void getZodiacTest() {
        // 摩羯座
        Console.log(Zodiac.getZodiac(Month.JANUARY, 19));
        // 天蝎座
        Console.log(Zodiac.getZodiac(Month.NOVEMBER, 1));
        // 天秤座
        Console.log(Zodiac.getZodiac(Month.OCTOBER, 15));
    }

    @Test
    public void getChineseZodiacTest() {
        // 狗
        Console.log(Zodiac.getChineseZodiac(1994));
        // 猪
        Console.log(Zodiac.getChineseZodiac(1995));
    }

    @Test
    public void isLeapYear() {
        // 是否是闰年
        Console.log(DateUtil.isLeapYear(2022));
        DateTime dateTime = DateUtil.parse("1995-10-15");
        // 年龄
        Console.log(DateUtil.ageOfNow(dateTime));
    }

异常工具 ExceptionUtil

    @Test
    public void getMessage() {
        RuntimeException runtimeException = new RuntimeException("hello world");
        String message = ExceptionUtil.getMessage(runtimeException);
        Console.log(message);
    }

    @Test
    public void wrapRuntime() {
        RuntimeException runtimeException = ExceptionUtil.wrapRuntime("hello world");
        Console.log(runtimeException);
    }

    @Test
    public void getCausedBy() {
        RuntimeException runtimeException = new RuntimeException("hello world");
        Throwable throwable = ExceptionUtil.getCausedBy(runtimeException, RuntimeException.class);
        Console.log(throwable);
    }

    @Test
    public void stacktraceToString() {
        RuntimeException runtimeException = new RuntimeException("hello world");
        String message = ExceptionUtil.stacktraceToString(runtimeException);
        Console.log(message);
    }

图片处理工具类

    @Test
    public void scaleTest() {
        ImgUtil.scale(FileUtil.file("D:\\pictures\\hutool\\bg.jpg"), FileUtil.file("D:\\pictures\\hutool\\bg_result.jpg"), 0.8f);
    }

    @Test
    public void scaleByWidthAndHeightTest() {
        ImgUtil.scale(FileUtil.file("D:\\pictures\\hutool\\bg.jpg"), FileUtil.file("D:\\pictures\\hutool\\bg_result2.jpg"), 400, 100, Color.BLUE);
    }

    @Test
    public void cutTest() {
        ImgUtil.cut(FileUtil.file("D:\\pictures\\hutool\\bg.jpg"), FileUtil.file("D:\\pictures\\hutool\\bg_cut.jpg"), new Rectangle(200, 200, 100, 100));
    }

    @Test
    public void rotateTest() throws IOException {
        Image image = ImgUtil.rotate(ImageIO.read(FileUtil.file("D:\\pictures\\hutool\\bg.jpg")), 180);
        ImgUtil.write(image, FileUtil.file("D:\\pictures\\hutool\\bg_rotate.jpg"));
    }

    @Test
    public void flipTest() {
        ImgUtil.flip(FileUtil.file("D:\\pictures\\hutool\\bg.jpg"), FileUtil.file("D:\\pictures\\hutool\\bg_flip.jpg"));
    }

    @Test
    public void pressImgTest() {
        ImgUtil.pressImage(
                FileUtil.file("D:\\pictures\\hutool\\bg.jpg"),
                FileUtil.file("D:\\pictures\\hutool\\bg_image.jpg"),
                ImgUtil.read(FileUtil.file("D:\\pictures\\hutool\\noonelikeu.jpg")), 0, 0, 0.9f);
    }

    @Test
    public void pressTextTest() {
        ImgUtil.pressText(//
                FileUtil.file("D:\\pictures\\hutool\\bg.jpg"), //
                FileUtil.file("D:\\pictures\\hutool\\bg_text.jpg"), //
                "版权所有", Color.RED, //
                new Font("黑体", Font.BOLD, 100), //
                0, //
                0, //
                1f);
    }

    @Test
    public void slice() {
        ImgUtil.slice(FileUtil.file("D:\\pictures\\hutool\\bg.jpg"), FileUtil.file("D:\\pictures\\hutool\\bg_slice.jpg"), 1, 5);
    }

    @Test
    public void convertTest() {
        ImgUtil.convert(FileUtil.file("D:\\pictures\\hutool\\bg.jpg"), FileUtil.file("D:\\pictures\\hutool\\bg_convert.png"));
    }

    @Test
    public void backgroundRemovalTest() {
        // 图片 背景 换成 透明的
        ImgUtil.backgroundRemoval(
                "D:\\pictures\\hutool\\noonelikeu.jpg",
                "D:\\pictures\\hutool\\noonelikeu_removal.jpg", 10);

        // 图片 背景 换成 红色的
        ImgUtil.backgroundRemoval(new File(
                        "D:\\pictures\\hutool\\noonelikeu.jpg"),
                new File("D:\\pictures\\hutool\\noonelikeu_red.jpg"),
                new Color(200, 0, 7), 10);
    }

IO 流相关

IO的操作包括读和写,应用场景包括网络操作和文件操作。IO操作在Java中是一个较为复杂的过程,我们在面对不同的场景时,要选择不同的InputStream和OutputStream实现来完成这些操作。而如果想读写字节流,还需要Reader和Writer的各种实现类。这些繁杂的实现类,一方面给我我们提供了更多的灵活性,另一方面也增加了复杂性。

    @Test
    public void copyTest() {
        BufferedInputStream inputStream = FileUtil.getInputStream("D:\\pictures\\hutool\\bg.jpg");
        BufferedOutputStream outputStream = FileUtil.getOutputStream("D:\\pictures\\hutool\\bg_out.jpg");
        IoUtil.copy(inputStream, outputStream);
    }

    @Test
    public void readLinesTest() {
        List<String> list = ListUtil.toList();
        try (BufferedReader reader = ResourceUtil.getUtf8Reader("io/test.csv")) {
            IoUtil.readLines(reader, list);
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
        for (String s : list) {
            Console.log(s);
        }
    }

Map工具-MapUtil

    @Test
    public void filterTest() {
        Map<String, String> map = MapUtil.newHashMap();
        map.put("a", "1");
        map.put("b", "2");
        map.put("c", "3");
        map.put("d", "4");

        Map<String, String> map2 = MapUtil.filter(map, t -> Convert.toInt(t.getValue()) % 2 == 0);
        // {b=2, d=4}
        Console.log(map2);
    }

    @Test
    public void editTest() {
        Map<String, String> map = MapUtil.newHashMap();
        map.put("a", "1");
        map.put("b", "2");
        map.put("c", "3");
        map.put("d", "4");

        Map<String, String> map2 = MapUtil.edit(map, t -> {
            // 修改每个值使之*10
            t.setValue(t.getValue() + "0");
            return t;
        });
        // {a=10, b=20, c=30, d=40}
        Console.log(map2);
    }

    @Test
    public void reverseTest() {
        Map<String, String> map = MapUtil.newHashMap();
        map.put("a", "1");
        map.put("b", "2");
        map.put("c", "3");
        map.put("d", "4");

        Map<String, String> map2 = MapUtil.reverse(map);

        // {1=a, 2=b, 3=c, 4=d}
        Console.log(map2);
    }

    @Test
    public void sortJoinTest() {
        Map<String, String> build = MapUtil.builder(new HashMap<String, String>())
                .put("key1", "value1")
                .put("key3", "value3")
                .put("key2", null).build();

        String join1 = MapUtil.sortJoin(build, "\n", "\t", false);
        // key1	value1
        // key2	null
        // key3	value3
        Console.log(join1);

        String join2 = MapUtil.sortJoin(build, "\n", "\t", true);
        // key1	value1
        // key3	value3
        Console.log(join2);

        String join3 = MapUtil.sortJoin(build, "\n", "\t", false, "123");
        // key1	value1
        // key2	null
        // key3	value3123
        Console.log(join3);

    }

    @Test
    public void getTest() {
        BiMap<String, Integer> biMap = new BiMap<>(new HashMap<>());
        biMap.put("aaa", 111);
        biMap.put("bbb", 222);
        // 111
        Console.log(biMap.get("aaa"));
        // bbb
        Console.log(biMap.getKey(222));
    }

数学相关-MathUtil

此工具是NumberUtil的一个补充,NumberUtil偏向于简单数学计算的封装,MathUtil偏向复杂数学计算。

如排列组合的计算

    @Test
    public void arrangementCount() {
        // A 4 4
        long result = MathUtil.arrangementCount(4);
        Console.log(result);
    }

    @Test
    public void arrangementSelect() {
        // A 4 2
        List<String[]> result = MathUtil.arrangementSelect(new String[]{"1", "2", "3", "4"}, 2);
        Console.log(result.size());
    }

    @Test
    public void combinationCount() {
        // C 4 4
        long result = MathUtil.combinationCount(4, 4);
        Console.log(result);
    }

    @Test
    public void combinationSelect() {
        // C 4 2
        List<String[]> result = MathUtil.combinationSelect(new String[]{"1", "2", "3", "4"}, 2);
        Console.log(result.size());
    }

    @Test
    public void calculate() {
        double conversion = Calculator.conversion("(0*1--3)-5/-4-(3*(-2.13))");
        Console.log(conversion);
    }

网络工具-NetUtil

    @Test
    public void getLocalhostStrTest() {
        String localhost = NetUtil.getLocalhostStr();
        Console.log(localhost);
    }

    @Test
    public void getLocalhostTest() {
        InetAddress localhost = NetUtil.getLocalhost();
        Console.log(localhost);
    }

    @Test
    public void getLocalMacAddressTest() {
        String macAddress = NetUtil.getLocalMacAddress();
        Console.log(macAddress);
    }
    
    @Test
    public void urlEncode() {
        String encode = FormUrlencoded.ALL.encode("https://www.baidu.com?token=1&key=2", CharsetUtil.CHARSET_UTF_8);
        Console.log(encode);
    }

    @Test
    public void urlDecode() {
        String decode = URLDecoder.decodeForPath("https%3A%2F%2Fwww.baidu.com%3Ftoken%3D1%26key%3D2", CharsetUtil.CHARSET_UTF_8);
        Console.log(decode);
    }

文本处理工具类

CSV 处理工具类

    @Test
    public void readTest() {
        CsvReader reader = CsvUtil.getReader();
        CsvData data = reader.read(ResourceUtil.getReader("text/test.csv", CharsetUtil.CHARSET_UTF_8));
        List<CsvRow> rows = data.getRows();
        for (CsvRow row : rows) {
            Console.log(row.getRawList());
        }
    }

    @Test
    public void readTest2() {
        CsvReader reader = CsvUtil.getReader();
        List<User> list = reader.read(ResourceUtil.getUtf8Reader("text/test_user.csv"), User.class);
        for (User user : list) {
            Console.log(user);
        }
    }

    @Test
    public void writeWithAliasTest() {
        CsvWriteConfig csvWriteConfig = CsvWriteConfig.defaultConfig()
                .addHeaderAlias("name", "姓名")
                .addHeaderAlias("gender", "性别")
                .addHeaderAlias("address", "地址");

        CsvWriter writer = CsvUtil.getWriter(
                FileUtil.file("C:\\Users\\fanzh23\\Desktop\\csv\\out.csv"),
                CharsetUtil.CHARSET_GBK, false, csvWriteConfig);

        writer.writeHeaderLine("name", "gender", "address");
        writer.writeLine("张三", "男", "XX市XX区");
        writer.writeLine("李四", "男", "XX市XX区,01号");
        writer.close();
    }

    @Test
    public void writeTest() {
        CsvWriter writer = CsvUtil.getWriter(
                FileUtil.file("C:\\Users\\fanzh23\\Desktop\\csv\\out_bean.csv"),
                CharsetUtil.CHARSET_GBK, false);
        List<User> list = new ArrayList<>();
        User student1 = new User();
        student1.setId(1);
        student1.setName("张三");
        student1.setAge(18);
        student1.setGender("男");

        User student2 = new User();
        student2.setId(2);
        student2.setName("李四");
        student2.setAge(22);
        student2.setGender("女");

        User student3 = new User();
        student3.setId(3);
        student3.setName("王五");
        student3.setAge(31);
        student3.setGender("男");

        list.add(student1);
        list.add(student2);
        list.add(student3);
        writer.writeBeans(list);
        writer.close();
    }
public class User {

    private Integer id;

    private String name;

    private Integer age;

    @Alias("性别")
    private String gender;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

unicode 处理工具类


    @Test
    public void convertTest() {
        String s = UnicodeUtil.toUnicode("aaa123中文", true);
        // "aaa123\\u4e2d\\u6587"
        Console.log(s);

        String s1 = UnicodeUtil.toString(s);
        // "aaa123中文"
        Console.log(s1);
    }
    

线程工具-ThreadUtil

    @Test
    public void executeTest() {
        ThreadUtil.execute(() -> Console.log("hello world"));
        ThreadUtil.safeSleep(1000);
    }

    @Test
    public void scheduleTest() {
        ThreadUtil.schedule(null, () -> {
            Console.log("hello world");
        }, 0, 1, TimeUnit.SECONDS, true);
        ThreadUtil.safeSleep(2000);
    }

    @Test
    public void asyncTest() throws ExecutionException, InterruptedException {
        Future<?> future = ThreadUtil.execAsync(() -> {
            Console.log("hello world");
            return "hello world";
        });
        ThreadUtil.safeSleep(2000);
        Console.log(future.get());
    }

    @Test
    public void testTest() {
        ConcurrencyTester tester = ThreadUtil.concurrencyTest(100, () -> {
            // 测试的逻辑内容
            long delay = RandomUtil.randomLong(100, 1000);
            ThreadUtil.sleep(delay);
            Console.log("{} test finished, delay: {}", Thread.currentThread().getName(), delay);
        });

        // 获取总的执行时间,单位毫秒
        Console.log(tester.getInterval());
    }

其他工具类

数组工具

    @Test
    public void isEmptyTest() {
        int[] a = {};
        Console.log(ArrayUtil.isEmpty(a));
        int[] b = null;
        Console.log(ArrayUtil.isEmpty(b));
    }

    @Test
    public void newArrayTest() {
        String[] newArray = ArrayUtil.newArray(String.class, 3);
        Console.log(newArray);
    }

    @Test
    public void rangeTest() {
        int[] range = ArrayUtil.range(0, 10);
        Assert.assertEquals(0, range[0]);
        Assert.assertEquals(1, range[1]);
        Assert.assertEquals(2, range[2]);
        Assert.assertEquals(3, range[3]);
        Assert.assertEquals(4, range[4]);
        Assert.assertEquals(5, range[5]);
        Assert.assertEquals(6, range[6]);
        Assert.assertEquals(7, range[7]);
        Assert.assertEquals(8, range[8]);
        Assert.assertEquals(9, range[9]);
    }

    @Test
    public void zipTest() {
        String[] keys = {"a", "b", "c"};
        Integer[] values = {1, 2, 3};
        Map<String, Integer> map = ArrayUtil.zip(keys, values, true);
        Console.log(map);
    }
类工具-ClassUtil

    @Test
    public void getClassNameTest() {
        String className = ClassUtil.getClassName(ClassUtil.class, false);
        Console.log(className);
        String simpleClassName = ClassUtil.getClassName(ClassUtil.class, true);
        Console.log(simpleClassName);
    }

    @Test
    public void getPublicMethod() {
        Method superPublicMethod = ClassUtil.getPublicMethod(TestSubClass.class, "publicMethod");
        Console.log(superPublicMethod);
        Method superPrivateMethod = ClassUtil.getDeclaredMethod(TestSubClass.class, "privateMethod");
        // 私有方法
        Console.log(superPrivateMethod);

        Method publicMethod = ClassUtil.getPublicMethod(TestSubClass.class, "publicSubMethod");
        Console.log(publicMethod);
        Method privateMethod = ClassUtil.getDeclaredMethod(TestSubClass.class, "privateSubMethod");
        Console.log(privateMethod);
    }

    @Test
    public void getDeclaredField() {
        // 不存在的字段
        Field noField = ClassUtil.getDeclaredField(TestSubClass.class, "noField");
        Console.log(noField);

        // 获取不到父类字段
        Field field = ClassUtil.getDeclaredField(TestSubClass.class, "field");
        Console.log(field);

        Field subField = ClassUtil.getDeclaredField(TestSubClass.class, "subField");
        Console.log(subField);
    }

    @Test
    public void getClassPathTest() {
        String classPath = ClassUtil.getClassPath();
        Console.log(classPath);
    }

    @Test
    public void getShortClassNameTest() {
        String className = "cn.hutool.core.util.StrUtil";
        String result = ClassUtil.getShortClassName(className);
        // c.h.c.u.StrUtil
        Console.log(result);
    }

    @Test
    public void getLocationPathTest() {
        String classDir = ClassUtil.getLocationPath(ClassUtilTest.class);
        Console.log(classDir);
    }
坐标系工具类

	@Test
	public void wgs84ToGcj02Test(){
		final CoordinateUtil.Coordinate coordinate = CoordinateUtil.wgs84ToGcj02(116.404, 39.915);
		Assert.assertEquals(116.41033392216508D, coordinate.getLng(), 0);
		Assert.assertEquals(39.91640428150164D, coordinate.getLat(), 0);
	}

	@Test
	public void gcj02ToWgs84Test(){
		final CoordinateUtil.Coordinate coordinate = CoordinateUtil.gcj02ToWgs84(116.404, 39.915);
		Assert.assertEquals(116.39766607783491D, coordinate.getLng(), 0);
		Assert.assertEquals(39.91359571849836D, coordinate.getLat(), 0);
	}

	@Test
	public void wgs84toBd09Test(){
		final CoordinateUtil.Coordinate coordinate = CoordinateUtil.wgs84ToBd09(116.404, 39.915);
		Assert.assertEquals(116.41671695444782D, coordinate.getLng(), 0);
		Assert.assertEquals(39.922698713521726D, coordinate.getLat(), 0);
	}

	@Test
	public void bd09toWgs84Test(){
		final CoordinateUtil.Coordinate coordinate = CoordinateUtil.bd09toWgs84(116.404, 39.915);
		Assert.assertEquals(116.39129143419822D, coordinate.getLng(), 0);
		Assert.assertEquals(39.907253214522164D, coordinate.getLat(), 0);
	}

	@Test
	public void gcj02ToBd09Test() {
		final CoordinateUtil.Coordinate coordinate = CoordinateUtil.gcj02ToBd09(116.404, 39.915);
		Assert.assertEquals(116.41036949371029D, coordinate.getLng(), 0);
		Assert.assertEquals(39.92133699351022D, coordinate.getLat(), 0);
	}

	@Test
	public void bd09toGcj02Test(){
		final CoordinateUtil.Coordinate coordinate = CoordinateUtil.bd09ToGcj02(116.404, 39.915);
		Assert.assertEquals(116.39762729119315D, coordinate.getLng(), 0);
		Assert.assertEquals(39.90865673957631D, coordinate.getLat(), 0);
	}
社会信用代码工具-CreditCodeUtil
  • 第一部分:登记管理部门代码1位 (数字或大写英文字母)
  • 第二部分:机构类别代码1位 (数字或大写英文字母)
  • 第三部分:登记管理机关行政区划码6位 (数字)
  • 第四部分:主体标识码(组织机构代码)9位 (数字或大写英文字母)
  • 第五部分:校验码1位 (数字或大写英文字母)

	@Test
	public void isCreditCodeBySimple() {
		String testCreditCode = "91310115591693856A";
		Assert.assertTrue(CreditCodeUtil.isCreditCodeSimple(testCreditCode));
	}

	@Test
	public void isCreditCode() {
		String testCreditCode = "91310110666007217T";
		Assert.assertTrue(CreditCodeUtil.isCreditCode(testCreditCode));
	}

	@Test
	public void isCreditCode2() {
		// 由于早期部分试点地区推行 法人和其他组织统一社会信用代码 较早,会存在部分代码不符合国家标准的情况。
		// 见:https://github.com/bluesky335/IDCheck
		String testCreditCode = "91350211M00013FA1N";
		Assert.assertFalse(CreditCodeUtil.isCreditCode(testCreditCode));
	}

	@Test
	public void randomCreditCode() {
		final String s = CreditCodeUtil.randomCreditCode();
		Assert.assertTrue(CreditCodeUtil.isCreditCode(s));
	}
信息脱敏工具-DesensitizedUtil

	@Test
	public void desensitizedTest() {
		Assert.assertEquals("0", DesensitizedUtil.desensitized("100", DesensitizedUtil.DesensitizedType.USER_ID));
		Assert.assertEquals("段**", DesensitizedUtil.desensitized("段正淳", DesensitizedUtil.DesensitizedType.CHINESE_NAME));
		Assert.assertEquals("5***************1X", DesensitizedUtil.desensitized("51343620000320711X", DesensitizedUtil.DesensitizedType.ID_CARD));
		Assert.assertEquals("0915*****79", DesensitizedUtil.desensitized("09157518479", DesensitizedUtil.DesensitizedType.FIXED_PHONE));
		Assert.assertEquals("180****1999", DesensitizedUtil.desensitized("18049531999", DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
		Assert.assertEquals("北京市海淀区马********", DesensitizedUtil.desensitized("北京市海淀区马连洼街道289号", DesensitizedUtil.DesensitizedType.ADDRESS));
		Assert.assertEquals("d*************@gmail.com.cn", DesensitizedUtil.desensitized("duandazhi-jack@gmail.com.cn", DesensitizedUtil.DesensitizedType.EMAIL));
		Assert.assertEquals("**********", DesensitizedUtil.desensitized("1234567890", DesensitizedUtil.DesensitizedType.PASSWORD));

		Assert.assertEquals("0", DesensitizedUtil.desensitized("100", DesensitizedUtil.DesensitizedType.USER_ID));
		Assert.assertEquals("段**", DesensitizedUtil.desensitized("段正淳", DesensitizedUtil.DesensitizedType.CHINESE_NAME));
		Assert.assertEquals("5***************1X", DesensitizedUtil.desensitized("51343620000320711X", DesensitizedUtil.DesensitizedType.ID_CARD));
		Assert.assertEquals("0915*****79", DesensitizedUtil.desensitized("09157518479", DesensitizedUtil.DesensitizedType.FIXED_PHONE));
		Assert.assertEquals("180****1999", DesensitizedUtil.desensitized("18049531999", DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
		Assert.assertEquals("北京市海淀区马********", DesensitizedUtil.desensitized("北京市海淀区马连洼街道289号", DesensitizedUtil.DesensitizedType.ADDRESS));
		Assert.assertEquals("d*************@gmail.com.cn", DesensitizedUtil.desensitized("duandazhi-jack@gmail.com.cn", DesensitizedUtil.DesensitizedType.EMAIL));
		Assert.assertEquals("**********", DesensitizedUtil.desensitized("1234567890", DesensitizedUtil.DesensitizedType.PASSWORD));
		Assert.assertEquals("1101 **** **** **** 3256", DesensitizedUtil.desensitized("11011111222233333256", DesensitizedUtil.DesensitizedType.BANK_CARD));
		Assert.assertEquals("6227 **** **** *** 5123", DesensitizedUtil.desensitized("6227880100100105123", DesensitizedUtil.DesensitizedType.BANK_CARD));
	}

	@Test
	public void userIdTest() {
		Assert.assertEquals(Long.valueOf(0L), DesensitizedUtil.userId());
	}

	@Test
	public void chineseNameTest() {
		Assert.assertEquals("段**", DesensitizedUtil.chineseName("段正淳"));
	}

	@Test
	public void idCardNumTest() {
		Assert.assertEquals("5***************1X", DesensitizedUtil.idCardNum("51343620000320711X", 1, 2));
	}

	@Test
	public void fixedPhoneTest() {
		Assert.assertEquals("0915*****79", DesensitizedUtil.fixedPhone("09157518479"));
	}

	@Test
	public void mobilePhoneTest() {
		Assert.assertEquals("180****1999", DesensitizedUtil.mobilePhone("18049531999"));
	}

	@Test
	public void addressTest() {
		Assert.assertEquals("北京市海淀区马连洼街*****", DesensitizedUtil.address("北京市海淀区马连洼街道289号", 5));
		Assert.assertEquals("***************", DesensitizedUtil.address("北京市海淀区马连洼街道289号", 50));
		Assert.assertEquals("北京市海淀区马连洼街道289号", DesensitizedUtil.address("北京市海淀区马连洼街道289号", 0));
		Assert.assertEquals("北京市海淀区马连洼街道289号", DesensitizedUtil.address("北京市海淀区马连洼街道289号", -1));
	}

	@Test
	public void emailTest() {
		Assert.assertEquals("d********@126.com", DesensitizedUtil.email("duandazhi@126.com"));
		Assert.assertEquals("d********@gmail.com.cn", DesensitizedUtil.email("duandazhi@gmail.com.cn"));
		Assert.assertEquals("d*************@gmail.com.cn", DesensitizedUtil.email("duandazhi-jack@gmail.com.cn"));
	}

	@Test
	public void passwordTest() {
		Assert.assertEquals("**********", DesensitizedUtil.password("1234567890"));
	}

	@Test
	public void carLicenseTest() {
		Assert.assertEquals("", DesensitizedUtil.carLicense(null));
		Assert.assertEquals("", DesensitizedUtil.carLicense(""));
		Assert.assertEquals("苏D4***0", DesensitizedUtil.carLicense("苏D40000"));
		Assert.assertEquals("陕A1****D", DesensitizedUtil.carLicense("陕A12345D"));
		Assert.assertEquals("京A123", DesensitizedUtil.carLicense("京A123"));
	}
枚举工具类 EnumUtil
    @Test
    public void getNamesTest() {
        List<String> names = EnumUtil.getNames(TestEnum.class);
        // [TEST1, TEST2, TEST3]
        Console.log(names);
    }

    @Test
    public void getFieldValuesTest() {
        List<Object> types = EnumUtil.getFieldValues(TestEnum.class, "type");
        // [type1, type2, type3]
        Console.log(types);
    }

    @Test
    public void getFieldNamesTest() {
        List<String> names = EnumUtil.getFieldNames(TestEnum.class);
        // [type, name]
        Console.log(names);
    }

    @Test
    public void getByTest() {
        // 枚举中字段互相映射使用
        TestEnum testEnum = EnumUtil.getBy(TestEnum::ordinal, 2);
        // type3
        Console.log(testEnum.getType());
    }

    @Test
    public void getFieldByTest() {
        // 枚举中字段互相映射使用
        String type = EnumUtil.getFieldBy(TestEnum::getType, Enum::ordinal, 2);
        // type3
        Console.log(type);
    }

    @Test
    public void getEnumMapTest() {
        Map<String, TestEnum> enumMap = EnumUtil.getEnumMap(TestEnum.class);
        // {TEST1=TEST1, TEST2=TEST2, TEST3=TEST3}
        Console.log(enumMap);
    }

    @Test
    public void getNameFieldMapTest() {
        Map<String, Object> enumMap = EnumUtil.getNameFieldMap(TestEnum.class, "type");
        // {TEST1=type1, TEST2=type2, TEST3=type3}
        Console.log(enumMap);
    }
Escape工具-EscapeUtil
    @Test
    public void escapeTest() {
        String str = "*@-_+./(123你好)ABCabc";
        String escape = EscapeUtil.escape(str);
        // *@-_+./%28123%u4f60%u597d%29ABCabc
        Console.log(escape);
        String unescape = EscapeUtil.unescape(escape);
        // *@-_+./(123你好)ABCabc
        Console.log(unescape);
    }

    @Test
    public void escapeAllTest() {
        String str = "*@-_+./(123你好)ABCabc";
        String escape = EscapeUtil.escapeAll(str);
        // %2a%40%2d%5f%2b%2e%2f%28%31%32%33%u4f60%u597d%29%41%42%43%61%62%63
        Console.log(escape);
        String unescape = EscapeUtil.unescape(escape);
        // *@-_+./(123你好)ABCabc
        Console.log(unescape);
    }
Hash算法-HashUtil

HashUtil其实是一个hash算法的集合,此工具类中融合了各种hash算法。

  • additiveHash 加法hash
  • rotatingHash 旋转hash
  • oneByOneHash 一次一个hash
  • bernstein Bernstein's hash
  • universal Universal Hashing
  • zobrist Zobrist Hashing
  • fnvHash 改进的32位FNV算法1
  • intHash Thomas Wang的算法,整数hash
  • rsHash RS算法hash
  • jsHash JS算法
  • pjwHash PJW算法
  • elfHash ELF算法
  • bkdrHash BKDR算法
  • sdbmHash SDBM算法
  • djbHash DJB算法
  • dekHash DEK算法
  • apHash AP算法
  • tianlHash TianL Hash算法
  • javaDefaultHash JAVA自己带的算法
  • mixHash 混合hash算法,输出64位的值
16进制工具-HexUtil
    @Test
    public void hexStrTest() {
        String str = "hello world";
        String hex = HexUtil.encodeHexStr(str, CharsetUtil.CHARSET_UTF_8);
        Console.log(hex);
        String decodedStr = HexUtil.decodeHexStr(hex);
        Console.log(decodedStr);
    }
身份证工具-IdcardUtil
    private static final String ID_18 = "321083197812162119";
    private static final String ID_15 = "150102880730303";

    @Test
    public void isValidCardTest() {
        boolean valid = IdcardUtil.isValidCard(ID_18);
        Console.log(valid);

        boolean valid15 = IdcardUtil.isValidCard(ID_15);
        Console.log(valid15);

        String invalidIdCard = "360198910283844";
        Console.log(IdcardUtil.isValidCard(invalidIdCard));

    }

    @Test
    public void convertTest() {
        String convert15To18 = IdcardUtil.convert15To18(ID_15);
        Console.log(convert15To18);
        String convert15To18Second = IdcardUtil.convert15To18("330102200403064");
        Console.log(convert15To18Second);
    }

    @Test
    public void getAgeByIdCardTest() {
        DateTime date = DateUtil.parse("2022-11-07");
        int age = IdcardUtil.getAgeByIdCard(ID_18, date);
        Console.log(age);
    }

    @Test
    public void getBirthByIdCardTest() {
        String birth = IdcardUtil.getBirthByIdCard(ID_18);
        Console.log(birth);
    }

    @Test
    public void getProvinceByIdCardTest() {
        String province = IdcardUtil.getProvinceByIdCard(ID_18);
        Console.log(province);
    }

    @Test
    public void getGenderByIdCardTest() {
        int gender = IdcardUtil.getGenderByIdCard(ID_18);
        // 17位 奇数位男性,偶数位女性
        Console.log(gender);
    }
唯一ID工具-IdUtil
    @Test
    public void randomUUIDTest() {
        String randomUUID = IdUtil.randomUUID();
        Console.log(randomUUID);
        String simpleUUID = IdUtil.simpleUUID();
        Console.log(simpleUUID);
    }

    @Test
    public void objectIdTest() {
        String objectId = IdUtil.objectId();
        Console.log(objectId);
    }

    @Test
    public void snowflakeTest() {
        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
        long id = snowflake.nextId();
        Console.log(id);
        // 简单使用
        long snowflakeNextId = IdUtil.getSnowflakeNextId();
        Console.log(snowflakeNextId);

    }

    @Test
    public void snowflakeBenchTest() {
        final Set<Long> set = new ConcurrentHashSet<>();
        final Snowflake snowflake = IdUtil.getSnowflake(1, 1);

        // 线程数
        int threadCount = 100;
        // 每个线程生成的ID数
        final int idCountPerThread = 10000;
        final CountDownLatch latch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            ThreadUtil.execute(() -> {
                for (int i1 = 0; i1 < idCountPerThread; i1++) {
                    long id = snowflake.nextId();
                    set.add(id);
                }
                latch.countDown();
            });
        }

        // 等待全部线程结束
        try {
            latch.await();
        } catch (InterruptedException e) {
            throw new UtilException(e);
        }
        Console.log("{},{}", threadCount * idCountPerThread, set.size());
    }


    /**
     * 性能测试
     */
    @Test
    public void benchTest() {
        int num = 10000000;
        TimeInterval timer = DateUtil.timer();
        for (int i = 0; i < num; i++) {
            UUID.randomUUID().toString().replace("-", "");
        }
        Console.log("jdk 的 uuid 生成:{}ms", timer.interval());

        timer.restart();
        for (int i = 0; i < num; i++) {
            IdUtil.simpleUUID();
        }
        Console.log("自定义 uuid 生成:{}ms", timer.interval());

        timer.restart();
        for (int i = 0; i < num; i++) {
            IdUtil.objectId();
        }
        Console.log("objectId 生成:{}ms", timer.interval());

        timer.restart();
        for (int i = 0; i < num; i++) {
            IdUtil.getSnowflakeNextId();
        }
        Console.log("雪花算法 生成:{}ms", timer.interval());
    }

数字工具类 NumberUtil
    @Test
    public void addTest() {
        Float a = 3.15f;
        Double b = 4.22;
        double result = NumberUtil.add(a, b).doubleValue();
        Console.log(result);
    }

    @Test
    public void divTest() {
        double result = NumberUtil.div(0, 1);
        Console.log(result);
    }

    @Test
    public void divBigDecimalTest() {
        // 四舍五入,保留3位
        BigDecimal result = NumberUtil.div(new BigDecimal("1"), new BigDecimal("3"), 3, RoundingMode.HALF_UP);
        Console.log(result);
    }

    @Test
    public void roundTest() {
        BigDecimal result = NumberUtil.round("2.647", 2, RoundingMode.HALF_UP);
        Console.log(result);
    }

    @Test
    public void decimalFormatTest() {
        long c = 299792458;
        // ,### -> 每三位以逗号进行分隔
        String format = NumberUtil.decimalFormat(",###", c);
        Console.log(format);
    }

    @Test
    public void range() {
        int[] range = NumberUtil.range(1, 10, 2);
        for (int i : range) {
            Console.log(i);
        }
    }
对象工具类 ObjectUtil
    @Test
    public void equalsTest() {
        Integer a = 1;
        Integer b = 1;
        Console.log(ObjectUtil.equal(a, b));
    }

    @Test
    public void lengthTest() {
        int[] array = new int[]{1, 2, 3, 4, 5};
        int length = ObjectUtil.length(array);
        Console.log(length);

        Map<String, String> map = new HashMap<>();
        map.put("a", "a1");
        map.put("b", "b1");
        map.put("c", "c1");
        length = ObjectUtil.length(map);
        Console.log(length);
    }

    @Test
    public void containsTest() {
        int[] array = new int[]{1, 2, 3, 4, 5};
        boolean contains = ObjectUtil.contains(array, 1);
        Console.log(contains);
    }
反射工具类 ReflectUtil
    @Test
    public void getFiledTest() {
        Field[] fields = ReflectUtil.getFields(ExamInfoDict.class, field -> field.getName().contains("id"));
        for (Field field : fields) {
            Console.log(field.getName());
        }
    }

    @Test
    public void getMethodsTest() {
        Method[] methods = ReflectUtil.getMethods(ExamInfoDict.class, method -> method.getName().contains("get"));
        for (Method method : methods) {
            Console.log(method.getName());
        }
    }

    @Test
    public void getMethodTest() {
        Method method = ReflectUtil.getMethod(ExamInfoDict.class, "getId");
        Console.log(method.getName());
    }

    @Test
    public void newInstance() {
        ExamInfoDict examInfoDict = ReflectUtil.newInstance(ExamInfoDict.class);
        Console.log(examInfoDict);
    }

    @Test
    public void invokeTest() {
        ExamInfoDict examInfoDict = new ExamInfoDict();
        ReflectUtil.invoke(examInfoDict, "setId", 1L);
        Object result = ReflectUtil.invoke(examInfoDict, "getId");
        Console.log(result);
    }

正则工具类
    final String content = "ZZZaaabbbccc中文1234";

    @Test
    public void getTest() {
        String resultGet = ReUtil.get("\\w{2}", content, 0);
        // ZZ
        Console.log(resultGet);
    }

    @Test
    public void extractMultiTest() {
        // 抽取多个分组然后把它们拼接起来
        String resultExtractMulti = ReUtil.extractMulti("(\\w)aa(\\w)", content, "$1-$2");
        // Z-a
        Console.log(resultExtractMulti);
    }

    @Test
    public void delFirstTest() {
        // 删除第一个匹配到的内容
        String resultDelFirst = ReUtil.delFirst("(\\w)aa(\\w)", content);
        // ZZbbbccc中文1234
        Console.log(resultDelFirst);
    }


    @Test
    public void delAllTest() {
        // 删除所有匹配到的内容
        String content = "发东方大厦eee![images]http://abc.com/2.gpg]好机会eee![images]http://abc.com/2.gpg]好机会";
        String resultDelAll = ReUtil.delAll("!\\[images\\][^\\u4e00-\\u9fa5\\\\s]*", content);
        // 发东方大厦eee好机会eee好机会
        Console.log(resultDelAll);
    }

    @Test
    public void findAllTest() {
        // 查找所有匹配文本
        List<String> resultFindAll = ReUtil.findAll("\\w{2}", content, 0, new ArrayList<>());
        // [ZZ, Za, aa, bb, bc, cc, 12, 34]
        Console.log(resultFindAll);
    }

    @Test
    public void getFirstNumberTest() {
        // 找到匹配的第一个数字
        Integer resultGetFirstNumber = ReUtil.getFirstNumber(content);
        // 1234
        Console.log(resultGetFirstNumber);
    }

    @Test
    public void isMatchTest() {
        // 给定字符串是否匹配给定正则
        boolean isMatch = ReUtil.isMatch("\\w+[\u4E00-\u9FFF]+\\d+", content);
        Console.log(isMatch);
    }

    @Test
    public void replaceAllTest() {
        //通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串
        //此处把1234替换为 ->1234<-
        String replaceAll = ReUtil.replaceAll(content, "(\\d+)", "->$1<-");
        // ZZZaaabbbccc中文->1234<-
        Console.log(replaceAll);
    }

    @Test
    public void getAllGroupsTest() {
        //转义给定字符串,为正则相关的特殊符号转义
        Pattern pattern = Pattern.compile("(\\d+)-(\\d+)-(\\d+)");
        List<String> allGroups = ReUtil.getAllGroups(pattern, "192-168-1-1");
        Console.log(allGroups);
        allGroups = ReUtil.getAllGroups(pattern, "192-168-1-1", false);
        Console.log(allGroups);
    }


    @Test
    public void getAllGroupNamesTest() {
        String content = "2021-10-11";
        String regex = "(?<year>\\d+)-(?<month>\\d+)-(?<day>\\d+)";
        Map<String, String> map = ReUtil.getAllGroupNames(PatternPool.get(regex, Pattern.DOTALL), content);
        Console.log(map);
    }
命令行工具类 RuntimeUtil
    @Test
    public void execTest() {
        String str = RuntimeUtil.execForStr("ipconfig");
        Console.log(str);
    }

    @Test
    public void execCmdTest() {
        String str = RuntimeUtil.execForStr("cmd /c dir");
        Console.log(str);
    }

    @Test
    public void getUsableMemoryTest() {
        Console.log(RuntimeUtil.getUsableMemory());
    }

    @Test
    public void getPidTest() {
        int pid = RuntimeUtil.getPid();
        Console.log(pid);
    }

    @Test
    public void getProcessorCountTest() {
        int cpu = RuntimeUtil.getProcessorCount();
        Console.log("cpu个数:{}", cpu);
    }
字符串工具类 StrUtil
    @Test
    public void isBlankTest() {
        String blank = "	   ";
        Console.log(StrUtil.isBlank(blank));
    }

    @Test
    public void trimTest() {
        String blank = "\r\n\t	 哈哈  ";
        String trim = StrUtil.trim(blank);
        Console.log(trim);
    }

    @Test
    public void cutTest() {
        String str = "aaabbbcccdddaadfdfsdfsdf0";
        String[] cut = StrUtil.cut(str, 4);
        Console.log(cut);
    }

    @Test
    public void splitTest() {
        String str = "a,b ,c,d,,e";
        List<String> split = StrUtil.split(str, ',', -1, true, true);
        // [a, b, c, d, e]
        Console.log(split);
        List<String> split2 = StrUtil.split(str, ',', -1, true, false);
        // [a, b, c, d, , e]
        Console.log(split2);
        List<String> split3 = StrUtil.split(str, ',', -1, false, true);
        // [a, b , c, d, e]
        Console.log(split3);
        List<String> split4 = StrUtil.split(str, ',');
        // [a, b , c, d, , e]
        Console.log(split4);
    }

    @Test
    public void formatTest() {
        String template = "你好,我是{name},我的电话是:{phone}";
        String result = StrUtil.format(template, Dict.create().set("name", "张三").set("phone", "13888881111"));
        Console.log(result);
        String result2 = StrUtil.format(template, Dict.create().set("name", "张三").set("phone", null));
        Console.log(result2);
    }

    @Test
    public void stripTest() {
        String str = "abcd123";
        String strip = StrUtil.strip(str, "ab", "23");
        Console.log(strip);
    }

    @Test
    public void repeatAndJoinTest() {
        String repeatAndJoin = StrUtil.repeatAndJoin("?", 5, ",");
        Console.log(repeatAndJoin);
    }

    @Test
    public void moveTest() {
        String str = "aaaaaaa22222bbbbbbb";
        String result = StrUtil.move(str, 7, 12, -3);
        Console.log(result);
    }

    @Test
    public void maxLengthTest() {
        String text = "我是一段正文,很长的正文,需要截取的正文";
        String str = StrUtil.maxLength(text, 5);
        Console.log(str);
    }

    @Test
    public void padTest() {
        // 001
        Console.log(StrUtil.padPre("1", 3, '0'));
        // 12
        Console.log(StrUtil.padPre("123", 2, '0'));
        // 100
        Console.log(StrUtil.padAfter("1", 3, '0'));
        // 23
        Console.log(StrUtil.padAfter("123", 2, '0'));
    }


    @Test
    public void briefTest() {
        // case: 1 至 str.length - 1
        String str = RandomUtil.randomString(RandomUtil.randomInt(1, 100));
        // case: 不会格式化的值
        Console.log(StrUtil.brief(str, 10));
        Console.log(StrUtil.brief(str, 0));
        Console.log(StrUtil.brief(str, -1));
        Console.log(StrUtil.brief(str, str.length()));
    }
泛型类型工具 TypeUtil

    @Test
    public void getEleTypeTest() {
        Method method = ReflectUtil.getMethod(TypeTestClass.class, "getList", Integer.class);
        // 获取入参类型
        Type paramType = TypeUtil.getParamType(method, 0);
        Console.log(paramType);
        // 获取返回值类型
        Type returnType = TypeUtil.getReturnType(method);
        Console.log(returnType);
        // 获取泛型
        Type genericType = TypeUtil.getTypeArgument(returnType);
        Console.log(genericType);
    }

    @Test
    public void getActualTypesTest() {
        // 测试多层级泛型参数是否能获取成功
        Type idType = TypeUtil.getActualType(Level3.class,
                ReflectUtil.getField(Level3.class, "id"));
        Console.log(idType);
    }

    public static class Level3 extends Level2<Level3> {

    }

    public static class Level2<E> extends Level1<Long> {

    }

    // @Data
    public static class Level1<T> {
        private T id;
    }
XML 工具类
    @Test
    public void readXmlTest() {
        Document document = XmlUtil.readXML(ResourceUtil.getReader("util/test.xml", CharsetUtil.CHARSET_UTF_8));
        String elementText = XmlUtil.elementText(document.getDocumentElement(), "returnstatus");
        Console.log(elementText);
    }

    @Test
    public void parseTest() {
        String result = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"//
                + "<returnsms>"//
                + "<returnstatus>Success</returnstatus>"//
                + "<message>ok</message>"//
                + "<remainpoint>1490</remainpoint>"//
                + "<taskID>885</taskID>"//
                + "<successCounts>1</successCounts>"//
                + "</returnsms>";
        Document docResult = XmlUtil.parseXml(result);
        String elementText = XmlUtil.elementText(docResult.getDocumentElement(), "returnstatus");
        Console.log(elementText);
    }

    @Test
    public void writeTest() {
        String result = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"//
                + "<returnsms>"//
                + "<returnstatus>Success(成功)</returnstatus>"//
                + "<message>ok</message>"//
                + "<remainpoint>1490</remainpoint>"//
                + "<taskID>885</taskID>"//
                + "<successCounts>1</successCounts>"//
                + "</returnsms>";
        Document docResult = XmlUtil.parseXml(result);
        XmlUtil.toFile(docResult, "C:\\Users\\fanzh23\\Desktop\\hutool\\test.xml", "utf-8");
    }

    @Test
    public void xpathTest() {
        Document document = XmlUtil.readXML(ResourceUtil.getReader("util/test.xml", CharsetUtil.CHARSET_UTF_8));
        Object value = XmlUtil.getByXPath("/returnsms/message", document, XPathConstants.STRING);
        Console.log(value);
    }

    @Test
    public void xmlToMapTest() {
        Document document = XmlUtil.readXML(ResourceUtil.getReader("util/test.xml", CharsetUtil.CHARSET_UTF_8));
        String xml = XmlUtil.toStr(document);
        Map<String, Object> map = XmlUtil.xmlToMap(xml);
        Console.log(map);
    }

    @Test
    public void mapToXmlTest() {
        Map<String, Object> map = MapBuilder.create(new LinkedHashMap<String, Object>())//
                .put("name", "张三")//
                .put("age", 12)//
                .put("game", MapUtil.builder(new LinkedHashMap<String, Object>()).put("昵称", "Looly").put("level", 14).build())//
                .build();
        Document doc = XmlUtil.mapToXml(map, "user");
        Console.log(XmlUtil.format(doc));
    }