mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
Merge branch 'v5-master' into feature/filter-readline
# Conflicts: # hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
This commit is contained in:
commit
8da20d7638
@ -8,3 +8,12 @@
|
|||||||
|
|
||||||
1. [bug修复] balabala……
|
1. [bug修复] balabala……
|
||||||
2. [新特性] balabala……
|
2. [新特性] balabala……
|
||||||
|
|
||||||
|
### 提交前自测
|
||||||
|
> 请在提交前自测确保代码没有问题,提交新代码应包含:测试用例、通过(mvn javadoc:javadoc)检验详细注释。
|
||||||
|
|
||||||
|
1. 本地如有多个JDK版本,可以设置临时JDk版本,如:`export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_331.jdk/Contents/Home`,具体替换为本地jdk目录
|
||||||
|
2. 确保本地测试使用JDK8最新版本,`echo $JAVA_HOME`、`mvn -v`、`java -version`均正确。
|
||||||
|
3. 执行打包生成文档,使用`mvn clean package -Dmaven.test.skip=true -U`,并确认通过,会自动执行打包、生成文档
|
||||||
|
4. 如需要单独执行文档生成,执行:`mvn javadoc:javadoc `,并确认通过
|
||||||
|
5. 如需要单独执行测试用例,执行:`mvn clean test`,并确认通过
|
||||||
|
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -8,3 +8,12 @@
|
|||||||
|
|
||||||
1. [bug修复] balabala……
|
1. [bug修复] balabala……
|
||||||
2. [新特性] balabala……
|
2. [新特性] balabala……
|
||||||
|
|
||||||
|
### 提交前自测
|
||||||
|
> 请在提交前自测确保代码没有问题,提交新代码应包含:测试用例、通过(mvn javadoc:javadoc)检验详细注释。
|
||||||
|
|
||||||
|
1. 本地如有多个JDK版本,可以设置临时JDk版本,如:`export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_331.jdk/Contents/Home`,具体替换为本地jdk目录
|
||||||
|
2. 确保本地测试使用JDK8最新版本,`echo $JAVA_HOME`、`mvn -v`、`java -version`均正确。
|
||||||
|
3. 执行打包生成文档,使用`mvn clean package -Dmaven.test.skip=true -U`,并确认通过,会自动执行打包、生成文档
|
||||||
|
4. 如需要单独执行文档生成,执行:`mvn javadoc:javadoc `,并确认通过
|
||||||
|
5. 如需要单独执行测试用例,执行:`mvn clean test`,并确认通过
|
2050
CHANGELOG.md
Normal file → Executable file
2050
CHANGELOG.md
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1878
CHANGELOG_5.0-5.7.md
Executable file
1878
CHANGELOG_5.0-5.7.md
Executable file
File diff suppressed because it is too large
Load Diff
20
README-EN.md
Normal file → Executable file
20
README-EN.md
Normal file → Executable file
@ -12,7 +12,7 @@
|
|||||||
<a target="_blank" href="https://search.maven.org/artifact/cn.hutool/hutool-all">
|
<a target="_blank" href="https://search.maven.org/artifact/cn.hutool/hutool-all">
|
||||||
<img src="https://img.shields.io/maven-central/v/cn.hutool/hutool-all.svg?label=Maven%20Central" />
|
<img src="https://img.shields.io/maven-central/v/cn.hutool/hutool-all.svg?label=Maven%20Central" />
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://license.coscl.org.cn/MulanPSL2/">
|
<a target="_blank" href="http://license.coscl.org.cn/MulanPSL2/index.html">
|
||||||
<img src="https://img.shields.io/:license-MulanPSL2-blue.svg" />
|
<img src="https://img.shields.io/:license-MulanPSL2-blue.svg" />
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
||||||
@ -40,8 +40,8 @@
|
|||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=jPq9DsjXs7GUWbXRZU3wygSJyMEy4pqr&jump_from=webapi">
|
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=QtsqXLkHpLjE99tkre19j6pjPMhSay1a&jump_from=webapi">
|
||||||
<img src="https://img.shields.io/badge/QQ%E7%BE%A4%E2%91%A5-610134978-orange"/></a>
|
<img src="https://img.shields.io/badge/QQ%E7%BE%A4%E2%91%A6-715292493-orange"/></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -51,7 +51,7 @@
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
## 📚Introduction
|
## 📚Introduction
|
||||||
**Hutool** is a small but comprehensive library of Java tools, encapsulation by static methods, reduce the cost of learning related APIs, increase productivity, and make Java as elegant as a functional programming language,let the Java be "sweet" too.
|
**Hutool** is a small but comprehensive library of Java tools, achieved by encapsulation through static methods, reduce the cost of learning related APIs, increase productivity, and make Java as elegant as a functional programming language,let the Java be "sweet" too.
|
||||||
|
|
||||||
**Hutool** tools and methods from each user's crafted, it covers all aspects of the underlying code of Java development, it is a powerful tool for large project development to solve small problems, but also the efficiency of small projects;
|
**Hutool** tools and methods from each user's crafted, it covers all aspects of the underlying code of Java development, it is a powerful tool for large project development to solve small problems, but also the efficiency of small projects;
|
||||||
|
|
||||||
@ -111,6 +111,8 @@ Each module can be introduced individually, or all modules can be introduced by
|
|||||||
|
|
||||||
[📘Chinese documentation](https://www.hutool.cn/docs/)
|
[📘Chinese documentation](https://www.hutool.cn/docs/)
|
||||||
|
|
||||||
|
[📘Chinese back-up documentation](https://plus.hutool.cn/docs/#/)
|
||||||
|
|
||||||
[📙API](https://apidoc.gitee.com/dromara/hutool/)
|
[📙API](https://apidoc.gitee.com/dromara/hutool/)
|
||||||
|
|
||||||
[🎬Video](https://www.bilibili.com/video/BV1bQ4y1M7d9?p=2)
|
[🎬Video](https://www.bilibili.com/video/BV1bQ4y1M7d9?p=2)
|
||||||
@ -131,7 +133,7 @@ If you think Hutool is good, you can donate to buy the author a pack of chili~,
|
|||||||
|
|
||||||
We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop:
|
We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop:
|
||||||
|
|
||||||
👉 [Hutool Shop](https://m.tb.cn/h.fVxoBOm?sm=2756b2) 👈
|
👉 [Hutool Shop](https://market.m.taobao.com/apps/market/content/index.html?wh_weex=true&contentId=331724720170) 👈
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -142,18 +144,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop:
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 🍐Gradle
|
### 🍐Gradle
|
||||||
```
|
```
|
||||||
implementation 'cn.hutool:hutool-all:5.7.15'
|
implementation 'cn.hutool:hutool-all:5.8.15'
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📥Download
|
## 📥Download
|
||||||
|
|
||||||
- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.15/)
|
- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.15/)
|
||||||
|
|
||||||
> 🔔️note:
|
> 🔔️note:
|
||||||
> Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available.
|
> Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available.
|
||||||
@ -205,8 +207,6 @@ Hutool welcomes anyone to contribute code to Hutool, but the author suffers from
|
|||||||
|
|
||||||
## ⭐Star Hutool
|
## ⭐Star Hutool
|
||||||
|
|
||||||
[](https://giteye.net/chart/GMSL7VDA)
|
|
||||||
|
|
||||||
[](https://starchart.cc/dromara/hutool)
|
[](https://starchart.cc/dromara/hutool)
|
||||||
|
|
||||||
## 📌WeChat Official Account
|
## 📌WeChat Official Account
|
||||||
|
24
README.md
Normal file → Executable file
24
README.md
Normal file → Executable file
@ -12,7 +12,7 @@
|
|||||||
<a target="_blank" href="https://search.maven.org/artifact/cn.hutool/hutool-all">
|
<a target="_blank" href="https://search.maven.org/artifact/cn.hutool/hutool-all">
|
||||||
<img src="https://img.shields.io/maven-central/v/cn.hutool/hutool-all.svg?label=Maven%20Central" />
|
<img src="https://img.shields.io/maven-central/v/cn.hutool/hutool-all.svg?label=Maven%20Central" />
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://license.coscl.org.cn/MulanPSL2/">
|
<a target="_blank" href="http://license.coscl.org.cn/MulanPSL2/index.html">
|
||||||
<img src="https://img.shields.io/:license-MulanPSL2-blue.svg" />
|
<img src="https://img.shields.io/:license-MulanPSL2-blue.svg" />
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
||||||
@ -40,8 +40,8 @@
|
|||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=jPq9DsjXs7GUWbXRZU3wygSJyMEy4pqr&jump_from=webapi">
|
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=QtsqXLkHpLjE99tkre19j6pjPMhSay1a&jump_from=webapi">
|
||||||
<img src="https://img.shields.io/badge/QQ%E7%BE%A4%E2%91%A5-610134978-orange"/></a>
|
<img src="https://img.shields.io/badge/QQ%E7%BE%A4%E2%91%A6-715292493-orange"/></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -107,6 +107,8 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
|||||||
|
|
||||||
[📘中文文档](https://www.hutool.cn/docs/)
|
[📘中文文档](https://www.hutool.cn/docs/)
|
||||||
|
|
||||||
|
[📘中文备用文档](https://plus.hutool.cn/docs/#/)
|
||||||
|
|
||||||
[📙参考API](https://apidoc.gitee.com/dromara/hutool/)
|
[📙参考API](https://apidoc.gitee.com/dromara/hutool/)
|
||||||
|
|
||||||
[🎬视频介绍](https://www.bilibili.com/video/BV1bQ4y1M7d9?p=2)
|
[🎬视频介绍](https://www.bilibili.com/video/BV1bQ4y1M7d9?p=2)
|
||||||
@ -129,7 +131,7 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
|||||||
|
|
||||||
我们提供了印有Hutool Logo的周边商品,欢迎点击购买支持:
|
我们提供了印有Hutool Logo的周边商品,欢迎点击购买支持:
|
||||||
|
|
||||||
👉 [Hutool 周边商店](https://m.tb.cn/h.fVxoBOm?sm=2756b2) 👈
|
👉 [Hutool 周边商店](https://market.m.taobao.com/apps/market/content/index.html?wh_weex=true&contentId=331724720170) 👈
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -142,20 +144,20 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 🍐Gradle
|
### 🍐Gradle
|
||||||
```
|
```
|
||||||
implementation 'cn.hutool:hutool-all:5.7.15'
|
implementation 'cn.hutool:hutool-all:5.8.15'
|
||||||
```
|
```
|
||||||
|
|
||||||
### 📥下载jar
|
### 📥下载jar
|
||||||
|
|
||||||
点击以下链接,下载`hutool-all-X.X.X.jar`即可:
|
点击以下链接,下载`hutool-all-X.X.X.jar`即可:
|
||||||
|
|
||||||
- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.15/)
|
- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.15/)
|
||||||
|
|
||||||
> 🔔️注意
|
> 🔔️注意
|
||||||
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
||||||
@ -209,18 +211,16 @@ Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过维护者是
|
|||||||
2. Hutool的缩进按照Eclipse(~~不要跟我说IDEA多好用,维护者非常懒,学不会~~,IDEA真香,改了Eclipse快捷键后舒服多了)默认(tab)缩进,所以请遵守(不要和我争执空格与tab的问题,这是一个病人的习惯)。
|
2. Hutool的缩进按照Eclipse(~~不要跟我说IDEA多好用,维护者非常懒,学不会~~,IDEA真香,改了Eclipse快捷键后舒服多了)默认(tab)缩进,所以请遵守(不要和我争执空格与tab的问题,这是一个病人的习惯)。
|
||||||
3. 新加的方法不要使用第三方库的方法,Hutool遵循无依赖原则(除非在extra模块中加方法工具)。
|
3. 新加的方法不要使用第三方库的方法,Hutool遵循无依赖原则(除非在extra模块中加方法工具)。
|
||||||
4. 请pull request到`v5-dev`分支。Hutool在5.x版本后使用了新的分支:`v5-master`是主分支,表示已经发布中央库的版本,这个分支不允许pr,也不允许修改。
|
4. 请pull request到`v5-dev`分支。Hutool在5.x版本后使用了新的分支:`v5-master`是主分支,表示已经发布中央库的版本,这个分支不允许pr,也不允许修改。
|
||||||
|
5. 我们如果关闭了你的issue或pr,请不要诧异,这是我们保持问题处理整洁的一种方式,你依旧可以继续讨论,当有讨论结果时我们会重新打开。
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
## ⭐Star Hutool
|
## ⭐Star Hutool
|
||||||
|
|
||||||
[](https://giteye.net/chart/GMSL7VDA)
|
|
||||||
|
|
||||||
[](https://starchart.cc/dromara/hutool)
|
[](https://starchart.cc/dromara/hutool)
|
||||||
|
|
||||||
## 📌公众号
|
## 📌 知识星球
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="https://cdn.jsdelivr.net/gh/looly/hutool-site/images/qr_tuling.jpg" height="150">
|
<img src="https://hutool.cn/images/dromara/zsxq.jpg" height="150">
|
||||||
<img src="https://dromara.org/img/qrcode/qrcode_1.png" height="150">
|
|
||||||
</div>
|
</div>
|
@ -7,5 +7,5 @@ echo ' / /_/ // / / // __// __ \ / __ \ / / '
|
|||||||
echo ' / __ // /_/ // /_ / /_/ // /_/ // / '
|
echo ' / __ // /_/ // /_ / /_/ // /_/ // / '
|
||||||
echo '/_/ /_/ \____/ \__/ \____/ \____//_/ '
|
echo '/_/ /_/ \____/ \__/ \____/ \____//_/ '
|
||||||
echo ''
|
echo ''
|
||||||
echo '-----------http://hutool.cn/------------'
|
echo '-----------https://hutool.cn/-----------'
|
||||||
echo '========================================'
|
echo '========================================'
|
||||||
|
@ -1 +1 @@
|
|||||||
5.7.15
|
5.8.15
|
||||||
|
2
docs/js/version.js
Normal file → Executable file
2
docs/js/version.js
Normal file → Executable file
@ -1 +1 @@
|
|||||||
var version = '5.7.15'
|
var version = '5.8.15'
|
2
hutool-all/pom.xml
Normal file → Executable file
2
hutool-all/pom.xml
Normal file → Executable file
@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
|
6
hutool-aop/pom.xml
Normal file → Executable file
6
hutool-aop/pom.xml
Normal file → Executable file
@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-aop</artifactId>
|
<artifactId>hutool-aop</artifactId>
|
||||||
@ -17,9 +17,10 @@
|
|||||||
<description>Hutool 动态代理(AOP)</description>
|
<description>Hutool 动态代理(AOP)</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<Automatic-Module-Name>cn.hutool.aop</Automatic-Module-Name>
|
||||||
<!-- versions -->
|
<!-- versions -->
|
||||||
<cglib.version>3.3.0</cglib.version>
|
<cglib.version>3.3.0</cglib.version>
|
||||||
<spring.version>5.3.10</spring.version>
|
<spring.version>5.3.23</spring.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -43,4 +44,5 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
0
hutool-aop/src/main/java/cn/hutool/aop/ProxyUtil.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/ProxyUtil.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/Aspect.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/Aspect.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/SimpleAspect.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/SimpleAspect.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/TimeIntervalAspect.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/TimeIntervalAspect.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/aspects/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/CglibInterceptor.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/CglibInterceptor.java
Normal file → Executable file
3
hutool-aop/src/main/java/cn/hutool/aop/interceptor/JdkInterceptor.java
Normal file → Executable file
3
hutool-aop/src/main/java/cn/hutool/aop/interceptor/JdkInterceptor.java
Normal file → Executable file
@ -54,12 +54,13 @@ public class JdkInterceptor implements InvocationHandler, Serializable {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 结束执行回调
|
// 结束执行回调
|
||||||
if (aspect.after(target, method, args, result)) {
|
if (aspect.after(target, method, args, result)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/SpringCglibInterceptor.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/SpringCglibInterceptor.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/CglibProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/CglibProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/SpringCglibProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/SpringCglibProxyFactory.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/java/cn/hutool/aop/proxy/package-info.java
Normal file → Executable file
0
hutool-aop/src/main/resources/META-INF/services/cn.hutool.aop.proxy.ProxyFactory
Normal file → Executable file
0
hutool-aop/src/main/resources/META-INF/services/cn.hutool.aop.proxy.ProxyFactory
Normal file → Executable file
0
hutool-aop/src/test/java/cn/hutool/aop/test/AopTest.java
Normal file → Executable file
0
hutool-aop/src/test/java/cn/hutool/aop/test/AopTest.java
Normal file → Executable file
7
hutool-bloomFilter/pom.xml
Normal file → Executable file
7
hutool-bloomFilter/pom.xml
Normal file → Executable file
@ -9,13 +9,17 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-bloomFilter</artifactId>
|
<artifactId>hutool-bloomFilter</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
<description>Hutool 布隆过滤器</description>
|
<description>Hutool 布隆过滤器</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<Automatic-Module-Name>cn.hutool.bloomfilter</Automatic-Module-Name>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
@ -23,4 +27,5 @@
|
|||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
2
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BitMapBloomFilter.java
Normal file → Executable file
2
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BitMapBloomFilter.java
Normal file → Executable file
@ -8,7 +8,7 @@ import cn.hutool.bloomfilter.filter.SDBMFilter;
|
|||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BlommFilter 实现 <br>
|
* BloomFilter 实现 <br>
|
||||||
* 1.构建hash算法 <br>
|
* 1.构建hash算法 <br>
|
||||||
* 2.散列hash映射到数组的bit位置 <br>
|
* 2.散列hash映射到数组的bit位置 <br>
|
||||||
* 3.验证<br>
|
* 3.验证<br>
|
||||||
|
22
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BitSetBloomFilter.java
Normal file → Executable file
22
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BitSetBloomFilter.java
Normal file → Executable file
@ -2,17 +2,19 @@ package cn.hutool.bloomfilter;
|
|||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
import cn.hutool.core.util.HashUtil;
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BloomFilter实现方式2,此方式使用BitSet存储。<br>
|
* BloomFilter实现方式2,此方式使用BitSet存储。<br>
|
||||||
* Hash算法的使用使用固定顺序,只需指定个数即可
|
* Hash算法的使用使用固定顺序,只需指定个数即可
|
||||||
* @author loolly
|
|
||||||
*
|
*
|
||||||
|
* @author loolly
|
||||||
*/
|
*/
|
||||||
public class BitSetBloomFilter implements BloomFilter {
|
public class BitSetBloomFilter implements BloomFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -36,14 +38,28 @@ public class BitSetBloomFilter implements BloomFilter{
|
|||||||
this.bitSet = new BitSet(this.bitSetSize);
|
this.bitSet = new BitSet(this.bitSetSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过文件初始化过滤器.
|
||||||
|
*
|
||||||
|
* @param path 文件路径
|
||||||
|
* @param charsetName 字符集
|
||||||
|
* @throws IOException IO异常
|
||||||
|
* @deprecated 请使用 {@link #init(String, Charset)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void init(String path, String charsetName) throws IOException {
|
||||||
|
init(path, CharsetUtil.charset(charsetName));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过文件初始化过滤器.
|
* 通过文件初始化过滤器.
|
||||||
*
|
*
|
||||||
* @param path 文件路径
|
* @param path 文件路径
|
||||||
* @param charset 字符集
|
* @param charset 字符集
|
||||||
* @throws IOException IO异常
|
* @throws IOException IO异常
|
||||||
|
* @since 5.8.0
|
||||||
*/
|
*/
|
||||||
public void init(String path, String charset) throws IOException {
|
public void init(String path, Charset charset) throws IOException {
|
||||||
BufferedReader reader = FileUtil.getReader(path, charset);
|
BufferedReader reader = FileUtil.getReader(path, charset);
|
||||||
try {
|
try {
|
||||||
String line;
|
String line;
|
||||||
@ -75,6 +91,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 判定是否包含指定字符串
|
* 判定是否包含指定字符串
|
||||||
|
*
|
||||||
* @param str 字符串
|
* @param str 字符串
|
||||||
* @return 是否包含,存在误差
|
* @return 是否包含,存在误差
|
||||||
*/
|
*/
|
||||||
@ -116,6 +133,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算Hash值
|
* 计算Hash值
|
||||||
|
*
|
||||||
* @param str 被计算Hash的字符串
|
* @param str 被计算Hash的字符串
|
||||||
* @param k Hash算法序号
|
* @param k Hash算法序号
|
||||||
* @return Hash值
|
* @return Hash值
|
||||||
|
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BloomFilter.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BloomFilter.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BloomFilterUtil.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BloomFilterUtil.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/BitMap.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/BitMap.java
Normal file → Executable file
6
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java
Normal file → Executable file
6
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java
Normal file → Executable file
@ -32,21 +32,21 @@ public class IntMap implements BitMap, Serializable {
|
|||||||
@Override
|
@Override
|
||||||
public void add(long i) {
|
public void add(long i) {
|
||||||
int r = (int) (i / BitMap.MACHINE32);
|
int r = (int) (i / BitMap.MACHINE32);
|
||||||
int c = (int) (i % BitMap.MACHINE32);
|
int c = (int) (i & (BitMap.MACHINE32 - 1));
|
||||||
ints[r] = ints[r] | (1 << c);
|
ints[r] = ints[r] | (1 << c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(long i) {
|
public boolean contains(long i) {
|
||||||
int r = (int) (i / BitMap.MACHINE32);
|
int r = (int) (i / BitMap.MACHINE32);
|
||||||
int c = (int) (i % BitMap.MACHINE32);
|
int c = (int) (i & (BitMap.MACHINE32 - 1));
|
||||||
return ((ints[r] >>> c) & 1) == 1;
|
return ((ints[r] >>> c) & 1) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(long i) {
|
public void remove(long i) {
|
||||||
int r = (int) (i / BitMap.MACHINE32);
|
int r = (int) (i / BitMap.MACHINE32);
|
||||||
int c = (int) (i % BitMap.MACHINE32);
|
int c = (int) (i & (BitMap.MACHINE32 - 1));
|
||||||
ints[r] &= ~(1 << c);
|
ints[r] &= ~(1 << c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java
Normal file → Executable file
6
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java
Normal file → Executable file
@ -32,21 +32,21 @@ public class LongMap implements BitMap, Serializable {
|
|||||||
@Override
|
@Override
|
||||||
public void add(long i) {
|
public void add(long i) {
|
||||||
int r = (int) (i / BitMap.MACHINE64);
|
int r = (int) (i / BitMap.MACHINE64);
|
||||||
long c = i % BitMap.MACHINE64;
|
long c = i & (BitMap.MACHINE64 - 1);
|
||||||
longs[r] = longs[r] | (1L << c);
|
longs[r] = longs[r] | (1L << c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(long i) {
|
public boolean contains(long i) {
|
||||||
int r = (int) (i / BitMap.MACHINE64);
|
int r = (int) (i / BitMap.MACHINE64);
|
||||||
long c = i % BitMap.MACHINE64;
|
long c = i & (BitMap.MACHINE64 - 1);
|
||||||
return ((longs[r] >>> c) & 1) == 1;
|
return ((longs[r] >>> c) & 1) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(long i) {
|
public void remove(long i) {
|
||||||
int r = (int) (i / BitMap.MACHINE64);
|
int r = (int) (i / BitMap.MACHINE64);
|
||||||
long c = i % BitMap.MACHINE64;
|
long c = i & (BitMap.MACHINE64 - 1);
|
||||||
longs[r] &= ~(1L << c);
|
longs[r] &= ~(1L << c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/package-info.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/package-info.java
Normal file → Executable file
6
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java
Normal file → Executable file
6
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java
Normal file → Executable file
@ -14,9 +14,11 @@ import cn.hutool.bloomfilter.bitMap.LongMap;
|
|||||||
public abstract class AbstractFilter implements BloomFilter {
|
public abstract class AbstractFilter implements BloomFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
protected static int DEFAULT_MACHINE_NUM = BitMap.MACHINE32;
|
||||||
|
|
||||||
private BitMap bm = null;
|
private BitMap bm = null;
|
||||||
|
|
||||||
protected long size = 0;
|
protected long size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
@ -34,7 +36,7 @@ public abstract class AbstractFilter implements BloomFilter {
|
|||||||
* @param maxValue 最大值
|
* @param maxValue 最大值
|
||||||
*/
|
*/
|
||||||
public AbstractFilter(long maxValue) {
|
public AbstractFilter(long maxValue) {
|
||||||
this(maxValue, BitMap.MACHINE32);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
13
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/DefaultFilter.java
Normal file → Executable file
13
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/DefaultFilter.java
Normal file → Executable file
@ -7,19 +7,14 @@ import cn.hutool.core.util.HashUtil;
|
|||||||
*
|
*
|
||||||
* @author loolly
|
* @author loolly
|
||||||
*/
|
*/
|
||||||
public class DefaultFilter extends AbstractFilter {
|
public class DefaultFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public DefaultFilter(long maxValue, int machineNumber) {
|
|
||||||
super(maxValue, machineNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultFilter(long maxValue) {
|
public DefaultFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public DefaultFilter(long maxValue, int machineNumber) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNumber, HashUtil::javaDefaultHash);
|
||||||
return HashUtil.javaDefaultHash(str) % size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/ELFFilter.java
Normal file → Executable file
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/ELFFilter.java
Normal file → Executable file
@ -2,20 +2,14 @@ package cn.hutool.bloomfilter.filter;
|
|||||||
|
|
||||||
import cn.hutool.core.util.HashUtil;
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
public class ELFFilter extends AbstractFilter {
|
public class ELFFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public ELFFilter(long maxValue, int machineNumber) {
|
|
||||||
super(maxValue, machineNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ELFFilter(long maxValue) {
|
public ELFFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public ELFFilter(long maxValue, int machineNumber) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNumber, HashUtil::elfHash);
|
||||||
return HashUtil.elfHash(str) % size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/FNVFilter.java
Normal file → Executable file
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/FNVFilter.java
Normal file → Executable file
@ -2,20 +2,14 @@ package cn.hutool.bloomfilter.filter;
|
|||||||
|
|
||||||
import cn.hutool.core.util.HashUtil;
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
public class FNVFilter extends AbstractFilter {
|
public class FNVFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public FNVFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FNVFilter(long maxValue) {
|
public FNVFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public FNVFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::fnvHash);
|
||||||
return HashUtil.fnvHash(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package cn.hutool.bloomfilter.filter;
|
||||||
|
|
||||||
|
import cn.hutool.bloomfilter.BloomFilter;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于Hash函数方法的{@link BloomFilter}
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 5.8.0
|
||||||
|
*/
|
||||||
|
public class FuncFilter extends AbstractFilter {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Function<String, Number> hashFunc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param maxValue 最大值
|
||||||
|
* @param hashFunc Hash函数
|
||||||
|
*/
|
||||||
|
public FuncFilter(long maxValue, Function<String, Number> hashFunc) {
|
||||||
|
this(maxValue, DEFAULT_MACHINE_NUM, hashFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxValue 最大值
|
||||||
|
* @param machineNum 机器位数
|
||||||
|
* @param hashFunc Hash函数
|
||||||
|
*/
|
||||||
|
public FuncFilter(long maxValue, int machineNum, Function<String, Number> hashFunc) {
|
||||||
|
super(maxValue, machineNum);
|
||||||
|
this.hashFunc = hashFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long hash(String str) {
|
||||||
|
return hashFunc.apply(str).longValue() % size;
|
||||||
|
}
|
||||||
|
}
|
27
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/HfFilter.java
Normal file → Executable file
27
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/HfFilter.java
Normal file → Executable file
@ -1,31 +1,16 @@
|
|||||||
package cn.hutool.bloomfilter.filter;
|
package cn.hutool.bloomfilter.filter;
|
||||||
|
|
||||||
|
|
||||||
public class HfFilter extends AbstractFilter {
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
|
public class HfFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public HfFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HfFilter(long maxValue) {
|
public HfFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public HfFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::hfHash);
|
||||||
int length = str.length() ;
|
|
||||||
long hash = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
hash += str.charAt(i) * 3 * i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hash < 0) {
|
|
||||||
hash = -hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash % size;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
21
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/HfIpFilter.java
Normal file → Executable file
21
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/HfIpFilter.java
Normal file → Executable file
@ -1,24 +1,15 @@
|
|||||||
package cn.hutool.bloomfilter.filter;
|
package cn.hutool.bloomfilter.filter;
|
||||||
|
|
||||||
public class HfIpFilter extends AbstractFilter {
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
|
public class HfIpFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public HfIpFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HfIpFilter(long maxValue) {
|
public HfIpFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public HfIpFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::hfIpHash);
|
||||||
int length = str.length();
|
|
||||||
long hash = 0;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
hash += str.charAt(i % 4) ^ str.charAt(i);
|
|
||||||
}
|
}
|
||||||
return hash % size;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
25
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/JSFilter.java
Normal file → Executable file
25
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/JSFilter.java
Normal file → Executable file
@ -1,30 +1,15 @@
|
|||||||
package cn.hutool.bloomfilter.filter;
|
package cn.hutool.bloomfilter.filter;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
public class JSFilter extends AbstractFilter {
|
public class JSFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public JSFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JSFilter(long maxValue) {
|
public JSFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public JSFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::jsHash);
|
||||||
int hash = 1315423911;
|
|
||||||
|
|
||||||
for (int i = 0; i < str.length(); i++) {
|
|
||||||
hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hash<0) {
|
|
||||||
hash*=-1 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash % size;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/PJWFilter.java
Normal file → Executable file
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/PJWFilter.java
Normal file → Executable file
@ -2,20 +2,14 @@ package cn.hutool.bloomfilter.filter;
|
|||||||
|
|
||||||
import cn.hutool.core.util.HashUtil;
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
public class PJWFilter extends AbstractFilter {
|
public class PJWFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public PJWFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PJWFilter(long maxValue) {
|
public PJWFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public PJWFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::pjwHash);
|
||||||
return HashUtil.pjwHash(str) % size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/RSFilter.java
Normal file → Executable file
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/RSFilter.java
Normal file → Executable file
@ -2,20 +2,14 @@ package cn.hutool.bloomfilter.filter;
|
|||||||
|
|
||||||
import cn.hutool.core.util.HashUtil;
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
public class RSFilter extends AbstractFilter {
|
public class RSFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public RSFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RSFilter(long maxValue) {
|
public RSFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public RSFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::rsHash);
|
||||||
return HashUtil.rsHash(str) % size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/SDBMFilter.java
Normal file → Executable file
14
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/SDBMFilter.java
Normal file → Executable file
@ -2,20 +2,14 @@ package cn.hutool.bloomfilter.filter;
|
|||||||
|
|
||||||
import cn.hutool.core.util.HashUtil;
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
public class SDBMFilter extends AbstractFilter {
|
public class SDBMFilter extends FuncFilter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public SDBMFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SDBMFilter(long maxValue) {
|
public SDBMFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public SDBMFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::sdbmHash);
|
||||||
return HashUtil.sdbmHash(str) % size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
15
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/TianlFilter.java
Normal file → Executable file
15
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/TianlFilter.java
Normal file → Executable file
@ -2,21 +2,14 @@ package cn.hutool.bloomfilter.filter;
|
|||||||
|
|
||||||
import cn.hutool.core.util.HashUtil;
|
import cn.hutool.core.util.HashUtil;
|
||||||
|
|
||||||
|
public class TianlFilter extends FuncFilter {
|
||||||
public class TianlFilter extends AbstractFilter {
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public TianlFilter(long maxValue, int machineNum) {
|
|
||||||
super(maxValue, machineNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TianlFilter(long maxValue) {
|
public TianlFilter(long maxValue) {
|
||||||
super(maxValue);
|
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public TianlFilter(long maxValue, int machineNum) {
|
||||||
public long hash(String str) {
|
super(maxValue, machineNum, HashUtil::tianlHash);
|
||||||
return HashUtil.tianlHash(str) % size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/package-info.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/package-info.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/package-info.java
Normal file → Executable file
0
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/package-info.java
Normal file → Executable file
0
hutool-bloomFilter/src/test/java/cn/hutool/bloomfilter/BitMapBloomFilterTest.java
Normal file → Executable file
0
hutool-bloomFilter/src/test/java/cn/hutool/bloomfilter/BitMapBloomFilterTest.java
Normal file → Executable file
2
hutool-bom/pom.xml
Normal file → Executable file
2
hutool-bom/pom.xml
Normal file → Executable file
@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-bom</artifactId>
|
<artifactId>hutool-bom</artifactId>
|
||||||
|
6
hutool-cache/pom.xml
Normal file → Executable file
6
hutool-cache/pom.xml
Normal file → Executable file
@ -9,13 +9,17 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-cache</artifactId>
|
<artifactId>hutool-cache</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
<description>Hutool 缓存</description>
|
<description>Hutool 缓存</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<Automatic-Module-Name>cn.hutool.cache</Automatic-Module-Name>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
|
0
hutool-cache/src/main/java/cn/hutool/cache/Cache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/Cache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/CacheListener.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/CacheListener.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/CacheUtil.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/CacheUtil.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/GlobalPruneTimer.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/GlobalPruneTimer.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/AbstractFileCache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/AbstractFileCache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/LFUFileCache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/LFUFileCache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/LRUFileCache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/LRUFileCache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/package-info.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/file/package-info.java
vendored
Normal file → Executable file
36
hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java
vendored
Normal file → Executable file
36
hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java
vendored
Normal file → Executable file
@ -3,14 +3,17 @@ package cn.hutool.cache.impl;
|
|||||||
import cn.hutool.cache.Cache;
|
import cn.hutool.cache.Cache;
|
||||||
import cn.hutool.cache.CacheListener;
|
import cn.hutool.cache.CacheListener;
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
|
import cn.hutool.core.lang.mutable.Mutable;
|
||||||
|
import cn.hutool.core.lang.mutable.MutableObj;
|
||||||
|
import cn.hutool.core.map.SafeConcurrentHashMap;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.LongAdder;
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 超时和限制大小的缓存的默认实现<br>
|
* 超时和限制大小的缓存的默认实现<br>
|
||||||
@ -27,12 +30,12 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
protected Map<K, CacheObj<K, V>> cacheMap;
|
protected Map<Mutable<K>, CacheObj<K, V>> cacheMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写的时候每个key一把锁,降低锁的粒度
|
* 写的时候每个key一把锁,降低锁的粒度
|
||||||
*/
|
*/
|
||||||
protected final Map<K, Lock> keyLockMap = new ConcurrentHashMap<>();
|
protected final SafeConcurrentHashMap<K, Lock> keyLockMap = new SafeConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回缓存容量,{@code 0}表示无大小限制
|
* 返回缓存容量,{@code 0}表示无大小限制
|
||||||
@ -84,7 +87,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
if (isFull()) {
|
if (isFull()) {
|
||||||
pruneCache();
|
pruneCache();
|
||||||
}
|
}
|
||||||
cacheMap.put(key, co);
|
cacheMap.put(MutableObj.of(key), co);
|
||||||
}
|
}
|
||||||
// ---------------------------------------------------------------- put end
|
// ---------------------------------------------------------------- put end
|
||||||
|
|
||||||
@ -112,7 +115,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
keyLock.lock();
|
keyLock.lock();
|
||||||
try {
|
try {
|
||||||
// 双重检查锁,防止在竞争锁的过程中已经有其它线程写入
|
// 双重检查锁,防止在竞争锁的过程中已经有其它线程写入
|
||||||
final CacheObj<K, V> co = cacheMap.get(key);
|
final CacheObj<K, V> co = getWithoutLock(key);
|
||||||
if (null == co || co.isExpired()) {
|
if (null == co || co.isExpired()) {
|
||||||
try {
|
try {
|
||||||
v = supplier.call();
|
v = supplier.call();
|
||||||
@ -130,6 +133,16 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取键对应的{@link CacheObj}
|
||||||
|
* @param key 键,实际使用时会被包装为{@link MutableObj}
|
||||||
|
* @return {@link CacheObj}
|
||||||
|
* @since 5.8.0
|
||||||
|
*/
|
||||||
|
protected CacheObj<K, V> getWithoutLock(K key){
|
||||||
|
return this.cacheMap.get(MutableObj.of(key));
|
||||||
|
}
|
||||||
// ---------------------------------------------------------------- get end
|
// ---------------------------------------------------------------- get end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -212,7 +225,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
* @since 5.5.9
|
* @since 5.5.9
|
||||||
*/
|
*/
|
||||||
public Set<K> keySet(){
|
public Set<K> keySet(){
|
||||||
return this.cacheMap.keySet();
|
return this.cacheMap.keySet().stream().map(Mutable::get).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,11 +250,20 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
* @return 移除的对象,无返回null
|
* @return 移除的对象,无返回null
|
||||||
*/
|
*/
|
||||||
protected CacheObj<K, V> removeWithoutLock(K key, boolean withMissCount) {
|
protected CacheObj<K, V> removeWithoutLock(K key, boolean withMissCount) {
|
||||||
final CacheObj<K, V> co = cacheMap.remove(key);
|
final CacheObj<K, V> co = cacheMap.remove(MutableObj.of(key));
|
||||||
if (withMissCount) {
|
if (withMissCount) {
|
||||||
// 在丢失计数有效的情况下,移除一般为get时的超时操作,此处应该丢失数+1
|
// 在丢失计数有效的情况下,移除一般为get时的超时操作,此处应该丢失数+1
|
||||||
this.missCount.increment();
|
this.missCount.increment();
|
||||||
}
|
}
|
||||||
return co;
|
return co;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有{@link CacheObj}值的{@link Iterator}形式
|
||||||
|
* @return {@link Iterator}
|
||||||
|
* @since 5.8.0
|
||||||
|
*/
|
||||||
|
protected Iterator<CacheObj<K, V>> cacheObjIter(){
|
||||||
|
return this.cacheMap.values().iterator();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
56
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java
vendored
Normal file → Executable file
56
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java
vendored
Normal file → Executable file
@ -1,14 +1,17 @@
|
|||||||
package cn.hutool.cache.impl;
|
package cn.hutool.cache.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存对象
|
* 缓存对象
|
||||||
* @author Looly
|
|
||||||
*
|
*
|
||||||
* @param <K> Key类型
|
* @param <K> Key类型
|
||||||
* @param <V> Value类型
|
* @param <V> Value类型
|
||||||
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class CacheObj<K, V> implements Serializable {
|
public class CacheObj<K, V> implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -16,12 +19,18 @@ public class CacheObj<K, V> implements Serializable{
|
|||||||
protected final K key;
|
protected final K key;
|
||||||
protected final V obj;
|
protected final V obj;
|
||||||
|
|
||||||
/** 上次访问时间 */
|
/**
|
||||||
private volatile long lastAccess;
|
* 上次访问时间
|
||||||
/** 访问次数 */
|
*/
|
||||||
|
protected volatile long lastAccess;
|
||||||
|
/**
|
||||||
|
* 访问次数
|
||||||
|
*/
|
||||||
protected AtomicLong accessCount = new AtomicLong();
|
protected AtomicLong accessCount = new AtomicLong();
|
||||||
/** 对象存活时长,0表示永久存活*/
|
/**
|
||||||
private final long ttl;
|
* 对象存活时长,0表示永久存活
|
||||||
|
*/
|
||||||
|
protected final long ttl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
@ -39,6 +48,7 @@ public class CacheObj<K, V> implements Serializable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取键
|
* 获取键
|
||||||
|
*
|
||||||
* @return 键
|
* @return 键
|
||||||
* @since 4.0.10
|
* @since 4.0.10
|
||||||
*/
|
*/
|
||||||
@ -48,6 +58,7 @@ public class CacheObj<K, V> implements Serializable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取值
|
* 获取值
|
||||||
|
*
|
||||||
* @return 值
|
* @return 值
|
||||||
* @since 4.0.10
|
* @since 4.0.10
|
||||||
*/
|
*/
|
||||||
@ -55,6 +66,39 @@ public class CacheObj<K, V> implements Serializable{
|
|||||||
return this.obj;
|
return this.obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对象存活时长,即超时总时长,0表示无限
|
||||||
|
*
|
||||||
|
* @return 对象存活时长
|
||||||
|
* @since 5.7.17
|
||||||
|
*/
|
||||||
|
public long getTtl() {
|
||||||
|
return this.ttl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取过期时间,返回{@code null}表示永不过期
|
||||||
|
*
|
||||||
|
* @return 此对象的过期时间,返回{@code null}表示永不过期
|
||||||
|
* @since 5.7.17
|
||||||
|
*/
|
||||||
|
public Date getExpiredTime(){
|
||||||
|
if(this.ttl > 0){
|
||||||
|
return DateUtil.date(this.lastAccess + this.ttl);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上次访问时间
|
||||||
|
*
|
||||||
|
* @return 上次访问时间
|
||||||
|
* @since 5.7.17
|
||||||
|
*/
|
||||||
|
public long getLastAccess() {
|
||||||
|
return this.lastAccess;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "CacheObj [key=" + key + ", obj=" + obj + ", lastAccess=" + lastAccess + ", accessCount=" + accessCount + ", ttl=" + ttl + "]";
|
return "CacheObj [key=" + key + ", obj=" + obj + ", lastAccess=" + lastAccess + ", accessCount=" + accessCount + ", ttl=" + ttl + "]";
|
||||||
|
0
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObjIterator.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObjIterator.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheValuesIterator.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheValuesIterator.java
vendored
Normal file → Executable file
4
hutool-cache/src/main/java/cn/hutool/cache/impl/FIFOCache.java
vendored
Normal file → Executable file
4
hutool-cache/src/main/java/cn/hutool/cache/impl/FIFOCache.java
vendored
Normal file → Executable file
@ -50,7 +50,7 @@ public class FIFOCache<K, V> extends StampedCache<K, V> {
|
|||||||
CacheObj<K, V> first = null;
|
CacheObj<K, V> first = null;
|
||||||
|
|
||||||
// 清理过期对象并找出链表头部元素(先入元素)
|
// 清理过期对象并找出链表头部元素(先入元素)
|
||||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
final Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||||
if (isPruneExpiredActive()) {
|
if (isPruneExpiredActive()) {
|
||||||
// 清理过期对象并找出链表头部元素(先入元素)
|
// 清理过期对象并找出链表头部元素(先入元素)
|
||||||
while (values.hasNext()) {
|
while (values.hasNext()) {
|
||||||
@ -71,7 +71,7 @@ public class FIFOCache<K, V> extends StampedCache<K, V> {
|
|||||||
|
|
||||||
// 清理结束后依旧是满的,则删除第一个被缓存的对象
|
// 清理结束后依旧是满的,则删除第一个被缓存的对象
|
||||||
if (isFull() && null != first) {
|
if (isFull() && null != first) {
|
||||||
cacheMap.remove(first.key);
|
removeWithoutLock(first.key, false);
|
||||||
onRemove(first.key, first.obj);
|
onRemove(first.key, first.obj);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
4
hutool-cache/src/main/java/cn/hutool/cache/impl/LFUCache.java
vendored
Normal file → Executable file
4
hutool-cache/src/main/java/cn/hutool/cache/impl/LFUCache.java
vendored
Normal file → Executable file
@ -57,7 +57,7 @@ public class LFUCache<K, V> extends StampedCache<K, V> {
|
|||||||
CacheObj<K, V> comin = null;
|
CacheObj<K, V> comin = null;
|
||||||
|
|
||||||
// 清理过期对象并找出访问最少的对象
|
// 清理过期对象并找出访问最少的对象
|
||||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||||
CacheObj<K, V> co;
|
CacheObj<K, V> co;
|
||||||
while (values.hasNext()) {
|
while (values.hasNext()) {
|
||||||
co = values.next();
|
co = values.next();
|
||||||
@ -78,7 +78,7 @@ public class LFUCache<K, V> extends StampedCache<K, V> {
|
|||||||
if (isFull() && comin != null) {
|
if (isFull() && comin != null) {
|
||||||
long minAccessCount = comin.accessCount.get();
|
long minAccessCount = comin.accessCount.get();
|
||||||
|
|
||||||
values = cacheMap.values().iterator();
|
values = cacheObjIter();
|
||||||
CacheObj<K, V> co1;
|
CacheObj<K, V> co1;
|
||||||
while (values.hasNext()) {
|
while (values.hasNext()) {
|
||||||
co1 = values.next();
|
co1 = values.next();
|
||||||
|
11
hutool-cache/src/main/java/cn/hutool/cache/impl/LRUCache.java
vendored
Normal file → Executable file
11
hutool-cache/src/main/java/cn/hutool/cache/impl/LRUCache.java
vendored
Normal file → Executable file
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.cache.impl;
|
package cn.hutool.cache.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.mutable.Mutable;
|
||||||
import cn.hutool.core.map.FixedLinkedHashMap;
|
import cn.hutool.core.map.FixedLinkedHashMap;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -42,7 +43,13 @@ public class LRUCache<K, V> extends ReentrantCache<K, V> {
|
|||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
|
|
||||||
//链表key按照访问顺序排序,调用get方法后,会将这次访问的元素移至头部
|
//链表key按照访问顺序排序,调用get方法后,会将这次访问的元素移至头部
|
||||||
cacheMap = new FixedLinkedHashMap<>(capacity);
|
final FixedLinkedHashMap<Mutable<K>, CacheObj<K, V>> fixedLinkedHashMap = new FixedLinkedHashMap<>(capacity);
|
||||||
|
fixedLinkedHashMap.setRemoveListener(entry -> {
|
||||||
|
if(null != listener){
|
||||||
|
listener.onRemove(entry.getKey().get(), entry.getValue().getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cacheMap = fixedLinkedHashMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------- prune
|
// ---------------------------------------------------------------- prune
|
||||||
@ -56,7 +63,7 @@ public class LRUCache<K, V> extends ReentrantCache<K, V> {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int count = 0;
|
int count = 0;
|
||||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||||
CacheObj<K, V> co;
|
CacheObj<K, V> co;
|
||||||
while (values.hasNext()) {
|
while (values.hasNext()) {
|
||||||
co = values.next();
|
co = values.next();
|
||||||
|
0
hutool-cache/src/main/java/cn/hutool/cache/impl/NoCache.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/impl/NoCache.java
vendored
Normal file → Executable file
18
hutool-cache/src/main/java/cn/hutool/cache/impl/ReentrantCache.java
vendored
Normal file → Executable file
18
hutool-cache/src/main/java/cn/hutool/cache/impl/ReentrantCache.java
vendored
Normal file → Executable file
@ -18,7 +18,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
// 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
|
// 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
|
||||||
// 最优的解决方案是使用Guava的ConcurrentLinkedHashMap,此处使用简化的互斥锁
|
// TODO 最优的解决方案是使用Guava的ConcurrentLinkedHashMap,此处使用简化的互斥锁
|
||||||
protected final ReentrantLock lock = new ReentrantLock();
|
protected final ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -36,7 +36,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
|||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
// 不存在或已移除
|
// 不存在或已移除
|
||||||
final CacheObj<K, V> co = cacheMap.get(key);
|
final CacheObj<K, V> co = getWithoutLock(key);
|
||||||
if (co == null) {
|
if (co == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
|||||||
CacheObj<K, V> co;
|
CacheObj<K, V> co;
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
co = cacheMap.get(key);
|
co = getWithoutLock(key);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
|||||||
CopiedIter<CacheObj<K, V>> copiedIterator;
|
CopiedIter<CacheObj<K, V>> copiedIterator;
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
copiedIterator = CopiedIter.copyOf(this.cacheMap.values().iterator());
|
copiedIterator = CopiedIter.copyOf(cacheObjIter());
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -115,6 +115,16 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
return super.toString();
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除key对应的对象
|
* 移除key对应的对象
|
||||||
*
|
*
|
||||||
|
8
hutool-cache/src/main/java/cn/hutool/cache/impl/StampedCache.java
vendored
Normal file → Executable file
8
hutool-cache/src/main/java/cn/hutool/cache/impl/StampedCache.java
vendored
Normal file → Executable file
@ -36,7 +36,7 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
|||||||
final long stamp = lock.readLock();
|
final long stamp = lock.readLock();
|
||||||
try {
|
try {
|
||||||
// 不存在或已移除
|
// 不存在或已移除
|
||||||
final CacheObj<K, V> co = cacheMap.get(key);
|
final CacheObj<K, V> co = getWithoutLock(key);
|
||||||
if (co == null) {
|
if (co == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -58,12 +58,12 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
|||||||
public V get(K key, boolean isUpdateLastAccess) {
|
public V get(K key, boolean isUpdateLastAccess) {
|
||||||
// 尝试读取缓存,使用乐观读锁
|
// 尝试读取缓存,使用乐观读锁
|
||||||
long stamp = lock.tryOptimisticRead();
|
long stamp = lock.tryOptimisticRead();
|
||||||
CacheObj<K, V> co = cacheMap.get(key);
|
CacheObj<K, V> co = getWithoutLock(key);
|
||||||
if(false == lock.validate(stamp)){
|
if(false == lock.validate(stamp)){
|
||||||
// 有写线程修改了此对象,悲观读
|
// 有写线程修改了此对象,悲观读
|
||||||
stamp = lock.readLock();
|
stamp = lock.readLock();
|
||||||
try {
|
try {
|
||||||
co = cacheMap.get(key);
|
co = getWithoutLock(key);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlockRead(stamp);
|
lock.unlockRead(stamp);
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
|||||||
CopiedIter<CacheObj<K, V>> copiedIterator;
|
CopiedIter<CacheObj<K, V>> copiedIterator;
|
||||||
final long stamp = lock.readLock();
|
final long stamp = lock.readLock();
|
||||||
try {
|
try {
|
||||||
copiedIterator = CopiedIter.copyOf(this.cacheMap.values().iterator());
|
copiedIterator = CopiedIter.copyOf(cacheObjIter());
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlockRead(stamp);
|
lock.unlockRead(stamp);
|
||||||
}
|
}
|
||||||
|
5
hutool-cache/src/main/java/cn/hutool/cache/impl/TimedCache.java
vendored
Normal file → Executable file
5
hutool-cache/src/main/java/cn/hutool/cache/impl/TimedCache.java
vendored
Normal file → Executable file
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.cache.impl;
|
package cn.hutool.cache.impl;
|
||||||
|
|
||||||
import cn.hutool.cache.GlobalPruneTimer;
|
import cn.hutool.cache.GlobalPruneTimer;
|
||||||
|
import cn.hutool.core.lang.mutable.Mutable;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -37,7 +38,7 @@ public class TimedCache<K, V> extends StampedCache<K, V> {
|
|||||||
* @param timeout 过期时长
|
* @param timeout 过期时长
|
||||||
* @param map 存储缓存对象的map
|
* @param map 存储缓存对象的map
|
||||||
*/
|
*/
|
||||||
public TimedCache(long timeout, Map<K, CacheObj<K, V>> map) {
|
public TimedCache(long timeout, Map<Mutable<K>, CacheObj<K, V>> map) {
|
||||||
this.capacity = 0;
|
this.capacity = 0;
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
this.cacheMap = map;
|
this.cacheMap = map;
|
||||||
@ -52,7 +53,7 @@ public class TimedCache<K, V> extends StampedCache<K, V> {
|
|||||||
@Override
|
@Override
|
||||||
protected int pruneCache() {
|
protected int pruneCache() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
final Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||||
CacheObj<K, V> co;
|
CacheObj<K, V> co;
|
||||||
while (values.hasNext()) {
|
while (values.hasNext()) {
|
||||||
co = values.next();
|
co = values.next();
|
||||||
|
23
hutool-cache/src/main/java/cn/hutool/cache/impl/WeakCache.java
vendored
Normal file → Executable file
23
hutool-cache/src/main/java/cn/hutool/cache/impl/WeakCache.java
vendored
Normal file → Executable file
@ -1,6 +1,11 @@
|
|||||||
package cn.hutool.cache.impl;
|
package cn.hutool.cache.impl;
|
||||||
|
|
||||||
import java.util.WeakHashMap;
|
import cn.hutool.cache.CacheListener;
|
||||||
|
import cn.hutool.core.lang.Opt;
|
||||||
|
import cn.hutool.core.lang.mutable.Mutable;
|
||||||
|
import cn.hutool.core.map.WeakConcurrentMap;
|
||||||
|
|
||||||
|
import java.lang.ref.Reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 弱引用缓存<br>
|
* 弱引用缓存<br>
|
||||||
@ -17,8 +22,22 @@ import java.util.WeakHashMap;
|
|||||||
public class WeakCache<K, V> extends TimedCache<K, V>{
|
public class WeakCache<K, V> extends TimedCache<K, V>{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
* @param timeout 超时时常,单位毫秒,-1或0表示无限制
|
||||||
|
*/
|
||||||
public WeakCache(long timeout) {
|
public WeakCache(long timeout) {
|
||||||
super(timeout, new WeakHashMap<>());
|
super(timeout, new WeakConcurrentMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WeakCache<K, V> setListener(CacheListener<K, V> listener) {
|
||||||
|
super.setListener(listener);
|
||||||
|
|
||||||
|
final WeakConcurrentMap<Mutable<K>, CacheObj<K, V>> map = (WeakConcurrentMap<Mutable<K>, CacheObj<K, V>>) this.cacheMap;
|
||||||
|
// WeakKey回收之后,key对应的值已经是null了,因此此处的key也为null
|
||||||
|
map.setPurgeListener((key, value)-> listener.onRemove(Opt.ofNullable(key).map(Reference::get).map(Mutable::get).get(), value.getValue()));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
0
hutool-cache/src/main/java/cn/hutool/cache/impl/package-info.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/impl/package-info.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/package-info.java
vendored
Normal file → Executable file
0
hutool-cache/src/main/java/cn/hutool/cache/package-info.java
vendored
Normal file → Executable file
0
hutool-cache/src/test/java/cn/hutool/cache/CacheConcurrentTest.java
vendored
Normal file → Executable file
0
hutool-cache/src/test/java/cn/hutool/cache/CacheConcurrentTest.java
vendored
Normal file → Executable file
7
hutool-cache/src/test/java/cn/hutool/cache/CacheTest.java
vendored
Normal file → Executable file
7
hutool-cache/src/test/java/cn/hutool/cache/CacheTest.java
vendored
Normal file → Executable file
@ -61,6 +61,13 @@ public class CacheTest {
|
|||||||
Assert.assertNull(value3);
|
Assert.assertNull(value3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void lfuCacheTest2(){
|
||||||
|
Cache<String, String> lfuCache = CacheUtil.newLFUCache(3);
|
||||||
|
final String s = lfuCache.get(null);
|
||||||
|
Assert.assertNull(s);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lruCacheTest(){
|
public void lruCacheTest(){
|
||||||
Cache<String, String> lruCache = CacheUtil.newLRUCache(3);
|
Cache<String, String> lruCache = CacheUtil.newLRUCache(3);
|
||||||
|
0
hutool-cache/src/test/java/cn/hutool/cache/FileCacheTest.java
vendored
Normal file → Executable file
0
hutool-cache/src/test/java/cn/hutool/cache/FileCacheTest.java
vendored
Normal file → Executable file
46
hutool-cache/src/test/java/cn/hutool/cache/LRUCacheTest.java
vendored
Normal file → Executable file
46
hutool-cache/src/test/java/cn/hutool/cache/LRUCacheTest.java
vendored
Normal file → Executable file
@ -1,10 +1,15 @@
|
|||||||
package cn.hutool.cache;
|
package cn.hutool.cache;
|
||||||
|
|
||||||
import cn.hutool.cache.impl.LRUCache;
|
import cn.hutool.cache.impl.LRUCache;
|
||||||
|
import cn.hutool.core.thread.ThreadUtil;
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 见:https://github.com/dromara/hutool/issues/1895<br>
|
* 见:https://github.com/dromara/hutool/issues/1895<br>
|
||||||
@ -13,17 +18,29 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
*/
|
*/
|
||||||
public class LRUCacheTest {
|
public class LRUCacheTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void putTest(){
|
||||||
|
//https://github.com/dromara/hutool/issues/2227
|
||||||
|
final LRUCache<String, String> cache = CacheUtil.newLRUCache(100, 10);
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
//ThreadUtil.execute(()-> cache.put(RandomUtil.randomString(5), "1243", 10));
|
||||||
|
ThreadUtil.execute(()-> cache.get(RandomUtil.randomString(5), ()->RandomUtil.randomString(10)));
|
||||||
|
}
|
||||||
|
ThreadUtil.sleep(3000);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readWriteTest() throws InterruptedException {
|
public void readWriteTest() throws InterruptedException {
|
||||||
LRUCache<Integer, Integer> cache = CacheUtil.newLRUCache(10);
|
final LRUCache<Integer, Integer> cache = CacheUtil.newLRUCache(10);
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
cache.put(i, i);
|
cache.put(i, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
CountDownLatch countDownLatch = new CountDownLatch(10);
|
final CountDownLatch countDownLatch = new CountDownLatch(10);
|
||||||
// 10个线程分别读0-9 10000次
|
// 10个线程分别读0-9 10000次
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
int finalI = i;
|
final int finalI = i;
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
for (int j = 0; j < 10000; j++) {
|
for (int j = 0; j < 10000; j++) {
|
||||||
cache.get(finalI);
|
cache.get(finalI);
|
||||||
@ -34,7 +51,7 @@ public class LRUCacheTest {
|
|||||||
// 等待读线程结束
|
// 等待读线程结束
|
||||||
countDownLatch.await();
|
countDownLatch.await();
|
||||||
// 按顺序读0-9
|
// 按顺序读0-9
|
||||||
StringBuilder sb1 = new StringBuilder();
|
final StringBuilder sb1 = new StringBuilder();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
sb1.append(cache.get(i));
|
sb1.append(cache.get(i));
|
||||||
}
|
}
|
||||||
@ -43,10 +60,29 @@ public class LRUCacheTest {
|
|||||||
// 新加11,此时0最久未使用,应该淘汰0
|
// 新加11,此时0最久未使用,应该淘汰0
|
||||||
cache.put(11, 11);
|
cache.put(11, 11);
|
||||||
|
|
||||||
StringBuilder sb2 = new StringBuilder();
|
final StringBuilder sb2 = new StringBuilder();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
sb2.append(cache.get(i));
|
sb2.append(cache.get(i));
|
||||||
}
|
}
|
||||||
Assert.assertEquals("null123456789", sb2.toString());
|
Assert.assertEquals("null123456789", sb2.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void issue2647Test(){
|
||||||
|
final AtomicInteger removeCount = new AtomicInteger();
|
||||||
|
|
||||||
|
final LRUCache<String, Integer> cache = CacheUtil.newLRUCache(3,1);
|
||||||
|
cache.setListener((key, value) -> {
|
||||||
|
// 共移除7次
|
||||||
|
removeCount.incrementAndGet();
|
||||||
|
//Console.log("Start remove k-v, key:{}, value:{}", key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
cache.put(StrUtil.format("key-{}", i), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertEquals(7, removeCount.get());
|
||||||
|
Assert.assertEquals(3, cache.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
51
hutool-cache/src/test/java/cn/hutool/cache/WeakCacheTest.java
vendored
Executable file
51
hutool-cache/src/test/java/cn/hutool/cache/WeakCacheTest.java
vendored
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
package cn.hutool.cache;
|
||||||
|
|
||||||
|
import cn.hutool.cache.impl.WeakCache;
|
||||||
|
import cn.hutool.core.lang.Console;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class WeakCacheTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void removeTest(){
|
||||||
|
final WeakCache<String, String> cache = new WeakCache<>(-1);
|
||||||
|
cache.put("abc", "123");
|
||||||
|
cache.put("def", "456");
|
||||||
|
|
||||||
|
Assert.assertEquals(2, cache.size());
|
||||||
|
|
||||||
|
// 检查被MutableObj包装的key能否正常移除
|
||||||
|
cache.remove("abc");
|
||||||
|
|
||||||
|
Assert.assertEquals(1, cache.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void removeByGcTest(){
|
||||||
|
// https://gitee.com/dromara/hutool/issues/I51O7M
|
||||||
|
WeakCache<String, String> cache = new WeakCache<>(-1);
|
||||||
|
cache.put("a", "1");
|
||||||
|
cache.put("b", "2");
|
||||||
|
|
||||||
|
// 监听
|
||||||
|
Assert.assertEquals(2, cache.size());
|
||||||
|
cache.setListener(Console::log);
|
||||||
|
|
||||||
|
// GC测试
|
||||||
|
int i=0;
|
||||||
|
while(true){
|
||||||
|
if(2 == cache.size()){
|
||||||
|
i++;
|
||||||
|
Console.log("Object is alive for {} loops - ", i);
|
||||||
|
System.gc();
|
||||||
|
}else{
|
||||||
|
Console.log("Object has been collected.");
|
||||||
|
Console.log(cache.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
hutool-captcha/pom.xml
Normal file → Executable file
7
hutool-captcha/pom.xml
Normal file → Executable file
@ -9,13 +9,17 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-captcha</artifactId>
|
<artifactId>hutool-captcha</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
<description>Hutool 验证码工具</description>
|
<description>Hutool 验证码工具</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<Automatic-Module-Name>cn.hutool.captcha</Automatic-Module-Name>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
@ -23,4 +27,5 @@
|
|||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
0
hutool-captcha/src/main/java/cn/hutool/captcha/AbstractCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/AbstractCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/CaptchaUtil.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/CaptchaUtil.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/CircleCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/CircleCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/GifCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/GifCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/ICaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/ICaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/LineCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/LineCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/ShearCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/ShearCaptcha.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/AbstractGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/AbstractGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/CodeGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/CodeGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/MathGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/MathGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/RandomGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/RandomGenerator.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/package-info.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/generator/package-info.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/package-info.java
Normal file → Executable file
0
hutool-captcha/src/main/java/cn/hutool/captcha/package-info.java
Normal file → Executable file
0
hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaTest.java
Normal file → Executable file
0
hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaTest.java
Normal file → Executable file
0
hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaUtilTest.java
Normal file → Executable file
0
hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaUtilTest.java
Normal file → Executable file
0
hutool-captcha/src/test/java/cn/hutool/captcha/GeneratorTest.java
Normal file → Executable file
0
hutool-captcha/src/test/java/cn/hutool/captcha/GeneratorTest.java
Normal file → Executable file
114
hutool-core/README.md
Executable file
114
hutool-core/README.md
Executable file
@ -0,0 +1,114 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="https://hutool.cn/"><img src="https://cdn.jsdelivr.net/gh/looly/hutool-site/images/logo.jpg" width="45%"></a>
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<strong>🍬A set of tools that keep Java sweet.</strong>
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
👉 <a href="https://hutool.cn">https://hutool.cn/</a> 👈
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## 📚Hutool-core 模块介绍
|
||||||
|
|
||||||
|
`Hutool-core`提供了最常使用的基础工具类,包括集合、Map、IO、线程、Bean、图片处理、线程并发等便捷工具。
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 🛠️包含内容
|
||||||
|
|
||||||
|
### 注解(annotation)
|
||||||
|
|
||||||
|
提供了注解工具类,以及一些注解封装。如`CombinationAnnotationElement`组合注解以及Alias别名注解等。
|
||||||
|
|
||||||
|
### bean(bean)
|
||||||
|
|
||||||
|
提供了Bean工具类,以及Bean属性解析、Bean拷贝、动态Bean等。
|
||||||
|
|
||||||
|
### 构建器(builder)
|
||||||
|
|
||||||
|
抽象了Builder接口,提供建造者模式的封装,并默认提供了包括equals封装、Bean构建封装、比较器封装等。
|
||||||
|
|
||||||
|
### 克隆(clone)
|
||||||
|
|
||||||
|
提供`Cloneable`接口,明确`clone`方法,并提供默认实现类。
|
||||||
|
|
||||||
|
### 编码(codec)
|
||||||
|
|
||||||
|
提供了BaseN编码(Base16、Base32、Base58、Base62、Base64)编码实现。并提供了包括BCD、PunyCode、百分号编码的实现。
|
||||||
|
同时提供了包括莫尔斯电码、凯撒密码、RotN这类有趣功能的实现。
|
||||||
|
|
||||||
|
### 集合(collection)
|
||||||
|
|
||||||
|
集合中主要是提供了针对`Iterator`实现类的工具封装方法`IterUtil`和集合类封装的工具类`CollUtil`,并提供了一些特别的集合封装。
|
||||||
|
|
||||||
|
### 比较器(comparator)
|
||||||
|
|
||||||
|
主要是一些比较器的实现,如Bean字段比较器、自定义函数比较器、版本比较器等。
|
||||||
|
|
||||||
|
### 动态编译(compiler)
|
||||||
|
|
||||||
|
提供`javax.tools.JavaCompiler`的包装简化服务,形成源码动态编译工具类`CompilerUtil`,完成代码动态编译及热部署。
|
||||||
|
|
||||||
|
### 压缩(compress)
|
||||||
|
|
||||||
|
主要针对`java.util.zip`中的相关类封装工具,提供Zip、Gzip、Zlib等格式的压缩解压缩封装,为`ZipUtil`提供服务。
|
||||||
|
|
||||||
|
### 转换(convert)
|
||||||
|
|
||||||
|
“万能”转换器,提供整套的类型转换方式。通过`Converter`接口和`ConverterRegistry`转换登记中心,完成任意数据类型转换和自定义转换。
|
||||||
|
|
||||||
|
### 日期时间(date)
|
||||||
|
|
||||||
|
提供`Date`、`Calendar`、`java.time`相关API的工具化封装。包括时间解析、格式化、偏移等。
|
||||||
|
|
||||||
|
### 异常(exceptions)
|
||||||
|
|
||||||
|
提供异常工具`ExceptionUtil`,以及一些工具内部使用的异常。
|
||||||
|
|
||||||
|
### getter接口(getter)
|
||||||
|
|
||||||
|
提供各种类型的get操作接口封装。
|
||||||
|
|
||||||
|
### 图片(img)
|
||||||
|
|
||||||
|
提供图片、绘图、字体等工具封装,并提供GIF生成器和解析器实现。
|
||||||
|
|
||||||
|
### IO流和文件(io)
|
||||||
|
|
||||||
|
提供IO流工具、文件工具、文件类型工具等,并提供流拷贝、Checksum、文件监听功能实现。
|
||||||
|
|
||||||
|
### 语言特性(lang)
|
||||||
|
|
||||||
|
超级大杂项,提供一些设计模式的抽象实现(如单例模式`Singleton`),还有正则、Id生成器、函数、Hash算法、可变对象、树形结构、字典等。
|
||||||
|
|
||||||
|
### Map(map)
|
||||||
|
|
||||||
|
提供Map工具类和各类Map实现封装,如行列键的Table实现、自定义键值对转换的Map、线程安全的WeakMap实现等。
|
||||||
|
|
||||||
|
### 数学(math)
|
||||||
|
|
||||||
|
提供简单数学计算封装,如排列组合、货币类等。
|
||||||
|
|
||||||
|
### 网络(net)
|
||||||
|
|
||||||
|
提供网络相关工具封装,以及Ip地址工具类、SSL工具类、URL编码解码等。
|
||||||
|
|
||||||
|
### StreamAPI封装(stream)
|
||||||
|
|
||||||
|
提供简单的Stream相关封装。
|
||||||
|
|
||||||
|
### Swing和AWT(swing)
|
||||||
|
|
||||||
|
提供桌面应用API的工具封装,如启动应用、控制键盘鼠标操作、截屏等功能。
|
||||||
|
|
||||||
|
### 文本字符串(text)
|
||||||
|
|
||||||
|
提供强大的字符串文本封装,包括字符转换、字符串查找、字符串替换、字符串切分、Unicode工具等,并提供CSV格式封装。
|
||||||
|
|
||||||
|
### 线程及并发(thread)
|
||||||
|
|
||||||
|
线程并发封装,包括线程工具、锁工具、`CompletableFuture`封装工具、线程池构建等。
|
||||||
|
|
||||||
|
### 工具杂项(util)
|
||||||
|
|
||||||
|
提供其他不便归类的杂项工具类。如数组、编码、字符、Class、坐标系、身份证、组织机构代码、脱敏、枚举、转义、XML、进制转换、随机数、反射、正则、SPI等各种工具。
|
5
hutool-core/pom.xml
Normal file → Executable file
5
hutool-core/pom.xml
Normal file → Executable file
@ -9,11 +9,14 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.7.15</version>
|
<version>5.8.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-core</artifactId>
|
<artifactId>hutool-core</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
<description>Hutool核心,包括集合、字符串、Bean等工具</description>
|
<description>Hutool核心,包括集合、字符串、Bean等工具</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<Automatic-Module-Name>cn.hutool.core</Automatic-Module-Name>
|
||||||
|
</properties>
|
||||||
</project>
|
</project>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user