{"id":17674673,"url":"https://github.com/duanluan/zutil","last_synced_at":"2025-04-13T06:41:06.802Z","repository":{"id":43470125,"uuid":"405593385","full_name":"duanluan/ZUtil","owner":"duanluan","description":"追求更快更全的 Java 工具类","archived":false,"fork":false,"pushed_at":"2025-04-06T13:24:13.000Z","size":7566,"stargazers_count":48,"open_issues_count":0,"forks_count":14,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-06T14:29:39.426Z","etag":null,"topics":["datetime","java","pinyin","regex","util"],"latest_commit_sha":null,"homepage":"https://duanluan.github.io/ZUtil/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/duanluan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["https://afdian.net/order/create?plan_id=1342d000fe9611edbdbc52540025c377","https://www.buymeacoffee.com/duanluan"]}},"created_at":"2021-09-12T08:57:08.000Z","updated_at":"2025-04-06T13:24:16.000Z","dependencies_parsed_at":"2023-02-15T10:01:02.784Z","dependency_job_id":"edbf120f-4705-4249-b354-73074e4acce4","html_url":"https://github.com/duanluan/ZUtil","commit_stats":{"total_commits":458,"total_committers":6,"mean_commits":76.33333333333333,"dds":0.04585152838427953,"last_synced_commit":"b79eea62e3647dd5657a6e8fed26f739adc1651e"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duanluan%2FZUtil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duanluan%2FZUtil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duanluan%2FZUtil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duanluan%2FZUtil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/duanluan","download_url":"https://codeload.github.com/duanluan/ZUtil/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248675434,"owners_count":21143763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["datetime","java","pinyin","regex","util"],"created_at":"2024-10-24T07:08:15.925Z","updated_at":"2025-04-13T06:41:06.792Z","avatar_url":"https://github.com/duanluan.png","language":"Java","funding_links":["https://afdian.net/order/create?plan_id=1342d000fe9611edbdbc52540025c377","https://www.buymeacoffee.com/duanluan"],"categories":[],"sub_categories":[],"readme":"![](https://socialify.git.ci/duanluan/ZUtil/image?description=1\u0026font=Bitter\u0026forks=1\u0026issues=1\u0026language=1\u0026logo=https%3A%2F%2Fduanluan.github.io%2FZUtil%2Fimg%2Flogo.png\u0026name=1\u0026owner=1\u0026pattern=Floating%20Cogs\u0026pulls=1\u0026stargazers=1\u0026theme=Light)\n\n# ZUtil\n\n[![](https://img.shields.io/hexpm/l/plug?style=for-the-badge\u0026logo=apache)](./LICENSE) \n[![](https://img.shields.io/maven-central/v/top.csaf/ZUtil?style=for-the-badge\u0026logo=apachemaven)](https://central.sonatype.com/artifact/top.csaf/zutil-all) \n[![](https://img.shields.io/badge/JDK-8%2B-orange?style=for-the-badge\u0026logo=openjdk)]() \n[![](https://img.shields.io/github/stars/duanluan/ZUtil?style=for-the-badge\u0026logo=github)](https://github.com/duanluan/ZUtil) \n[![GitHub commits](https://img.shields.io/github/commit-activity/m/duanluan/ZUtil?style=for-the-badge\u0026label=Commits\u0026logo=github)](https://github.com/duanluan/ZUtil/commits) \n[![](https://img.shields.io/badge/QQ%20group-273743748-e76970.svg?style=for-the-badge\u0026logo=tencentqq)](https://jq.qq.com/?_wv=1027\u0026k=pYzF0R18) \n\n追求更快更全的 Java 工具类。\n\n工具类使用请查看\u003ca href='https://duanluan.github.io/ZUtil' target='_blank' style='font-size:25px'\u003e文档\u003c/a\u003e、[javadoc](https://apidoc.gitee.com/duanluan/ZUtil)。\n\n和 Hutool 的性能对比测试请查看 [jmh.comparison](zutil-all/src/test/java/top/csaf/jmh/comparison)。\n\n## 特性\n\n* 更快：使用 [JMH](https://openjdk.org/projects/code-tools/jmh/) 进行[性能测试](https://github.com/duanluan/ZUtil/tree/main/zutil-all/src/test/java/top/csaf/jmh)。\n* 更全：[时间工具类](https://github.com/duanluan/ZUtil/blob/main/zutil-date/src/main/java/top/csaf/date/DateUtil.java) 130+ 个方法，2700+ 行；[正则工具类](https://github.com/duanluan/ZUtil/blob/main/zutil-regex/src/main/java/top/csaf/regex/RegExUtil.java) 80+ 个方法，1100+ 行。\n* 更安全：使用 [JUnit](https://junit.org/junit5) 进行套件测试，[JaCoCo](https://www.jacoco.org/jacoco/index.html) 进行[代码覆盖率测试](https://github.com/duanluan/ZUtil/tree/main/zutil-all/src/test/java/top/csaf/junit)，保证每行代码都符合预期，更少出 BUG。\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/duanluan/ZUtil.svg)](https://starchart.cc/duanluan/ZUtil)\n\n## 说明\n\n### 安装\n\n#### Maven\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003etop.csaf\u003c/groupId\u003e\n  \u003cartifactId\u003eZUtil\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.0-alpha13\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n#### Gradle\n\n```groovy\n// groovy\nimplementation 'top.csaf:ZUtil:2.0.0-alpha13'\n// kotlin\nimplementation(\"top.csaf:ZUtil:2.0.0-alpha13\")\n```\n\n### 安装注意\n\n工具包中已使用 slf4j-api 和 slf4j-simple，和 spring-boot-starter-web 同时使用时会冲突，需要手动排除。\n\n#### Maven\n\n```xml\n\u003c!-- 方式一：ZUtil 排除 slf4j --\u003e\n\u003cdependency\u003e\n  \u003cgroupId\u003etop.csaf\u003c/groupId\u003e\n  \u003cartifactId\u003eZUtil\u003c/artifactId\u003e\n   \u003cversion\u003e2.0.0-alpha13\u003c/version\u003e\n  \u003cexclusions\u003e\n    \u003cexclusion\u003e\n      \u003cgroupId\u003eorg.slf4j\u003c/groupId\u003e\n      \u003cartifactId\u003eslf4j-api\u003c/artifactId\u003e\n    \u003c/exclusion\u003e\n    \u003cexclusion\u003e\n      \u003cgroupId\u003eorg.slf4j\u003c/groupId\u003e\n      \u003cartifactId\u003eslf4j-simple\u003c/artifactId\u003e\n    \u003c/exclusion\u003e\n  \u003c/exclusions\u003e\n\u003c/dependency\u003e\n\n\u003c!-- 方式二：spring-boot-starter-web 排除 Logback --\u003e\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n  \u003cartifactId\u003espring-boot-starter-web\u003c/artifactId\u003e\n  \u003cexclusions\u003e\n    \u003cexclusion\u003e\n      \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n      \u003cartifactId\u003espring-boot-starter-logging\u003c/artifactId\u003e\n    \u003c/exclusion\u003e\n  \u003c/exclusions\u003e\n\u003c/dependency\u003e\n```\n\n#### Gradle\n\n参考：[Excluding transitive dependencies - Gradle User Manual](https://docs.gradle.org/current/userguide/dependency_downgrade_and_exclude.html#sec:excluding-transitive-deps)\n\n```groovy\n// groovy\ndependencies {\n  // 方式一：ZUtil 排除 slf4j\n   implementation('top.csaf:ZUtil:2.0.0-alpha13') {\n    exclude group: 'org.slf4j', module: 'slf4j-api'\n    exclude group: 'org.slf4j', module: 'slf4j-simple'\n  }\n  // 方式二：spring-boot-starter-web 排除 Logback\n  implementation('org.springframework.boot:spring-boot-starter-web') {\n    exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'\n  }\n}\n\n// kotlin\ndependencies {\n  // 方式一：ZUtil 排除 slf4j\n   implementation(\"top.csaf:ZUtil:2.0.0-alpha13\") {\n    exclude(group = \"org.slf4j\", module = \"slf4j-api\")\n    exclude(group = \"org.slf4j\", module = \"slf4j-simple\")\n  }\n  // 方式二：spring-boot-starter-web 排除 Logback\n  implementation(\"org.springframework.boot:spring-boot-starter-web\") {\n    exclude(group = \"org.springframework.boot\", module = \"spring-boot-starter-logging\")\n  }\n}\n```\n\n### JMH 性能对比测试结果解释\n\n```java\n// Benchmark                                                 Mode     Cnt    Score    Error   Units\n// ToPinyinTest.toPinyinByHutool                            thrpt       5    2.880 ±  0.160  ops/us\n// ToPinyinTest.toPinyinByZUtil                             thrpt       5    4.577 ±  0.133  ops/us\n// ToPinyinTest.toPinyinByHutool                             avgt       5    0.356 ±  0.012   us/op\n// ToPinyinTest.toPinyinByZUtil                              avgt       5    0.216 ±  0.006   us/op\n// ToPinyinTest.toPinyinByHutool                           sample  175058    0.435 ±  0.008   us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p0.00    sample            0.300            us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p0.50    sample            0.400            us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p0.90    sample            0.500            us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p0.95    sample            0.500            us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p0.99    sample            0.900            us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p0.999   sample            1.600            us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p0.9999  sample           40.900            us/op\n// ToPinyinTest.toPinyinByHutool:toPinyinByHutool·p1.00    sample          277.504            us/op\n// ToPinyinTest.toPinyinByZUtil                            sample  162384    0.393 ±  0.008   us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p0.00      sample            0.200            us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p0.50      sample            0.300            us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p0.90      sample            0.500            us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p0.95      sample            0.600            us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p0.99      sample            1.000            us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p0.999     sample            2.500            us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p0.9999    sample           45.425            us/op\n// ToPinyinTest.toPinyinByZUtil:toPinyinByZUtil·p1.00      sample          170.496            us/op\n// ToPinyinTest.toPinyinByHutool                               ss       5   30.880 ± 37.754   us/op\n// ToPinyinTest.toPinyinByZUtil                                ss       5   23.060 ± 16.885   us/op\n```\n\nMode 即为`org.openjdk.jmh.annotations.Mode`，分为：\n* thrpt：**Throughput（吞吐量）**, ops/time，分数越大越好\n* avgt：**Average time（平均时间）**, time/op，分数越小越好\n* sample：**Sampling time（采样时间）**，分数越小越好\n* ss：**Single shot invocation time（单次调用时间）**：分数越小越好\n\n### 参与开发\n\n1. **[Fork](https://github.com/duanluan/ZUtil/fork)** 并 **Clone** 项目到本地。\n2. 开发内容：\n   * **新增类或方法**需提前[加群](https://jq.qq.com/?_wv=1027\u0026k=pYzF0R18)沟通。\n   * **修复 BUG**（fix）、**优化性能**（perf）或**新增/更正测试**（test）。\n3. 测试步骤：\n   * 使用`org.junit.jupiter.api.Assertions`进行**代码覆盖率测试**：\n    ```java\n    ……\n    import top.csaf.id.NanoIdUtil;\n    import static org.junit.jupiter.api.Assertions.*;\n    \n    @Slf4j\n    @DisplayName(\"NanoId 工具类测试\")\n    class NanoIdUtilTest {\n    \n      @DisplayName(\"生成 NanoID\")\n      @Test\n      void randomNanoId() {\n        /** {@link NanoIdUtil#randomNanoId(int, char[], java.util.Random) } */\n        assertThrows(NullPointerException.class, () -\u003e NanoIdUtils.randomNanoId(0, (char[]) null, NanoIdUtils.DEFAULT_ID_GENERATOR));\n        assertThrows(NullPointerException.class, () -\u003e NanoIdUtils.randomNanoId(0, new char[0], null));\n        assertThrows(IllegalArgumentException.class, () -\u003e NanoIdUtils.randomNanoId(0, new char[0], NanoIdUtils.DEFAULT_ID_GENERATOR));\n        assertThrows(IllegalArgumentException.class, () -\u003e NanoIdUtils.randomNanoId(1, new char[0], NanoIdUtils.DEFAULT_ID_GENERATOR));\n        assertThrows(IllegalArgumentException.class, () -\u003e NanoIdUtils.randomNanoId(1, new char[256], NanoIdUtils.DEFAULT_ID_GENERATOR));\n        assertDoesNotThrow(() -\u003e NanoIdUtils.randomNanoId(NanoIdUtils.DEFAULT_SIZE, NanoIdUtils.DEFAULT_ALPHABET, NanoIdUtils.DEFAULT_ID_GENERATOR));\n      }\n    }\n    ```\n   * `mvn test -Dtest=要测试的类名`进行测试，测试后会在`target`下生成`jacoco.exec`。\n   * `mvn jacoco:report`生成代码覆盖率测试报告，在`target/site`目录下。\n   * 查看更新的类或方法，覆盖率在 **90%** 以上时提交。\n   * `lombok.NonNull`的参数校验可以忽略。\n4. 提交时遵循 **[Angular 提交消息规范](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines)**，提交后新建 **pull request** 即可。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduanluan%2Fzutil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fduanluan%2Fzutil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduanluan%2Fzutil/lists"}