mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +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
@ -7,4 +7,13 @@
|
||||
### 修改描述(包括说明bug修复或者添加新特性)
|
||||
|
||||
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`,并确认通过
|
||||
|
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -7,4 +7,13 @@
|
||||
### 修改描述(包括说明bug修复或者添加新特性)
|
||||
|
||||
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
22
README-EN.md
Normal file → Executable file
22
README-EN.md
Normal file → Executable file
@ -12,7 +12,7 @@
|
||||
<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" />
|
||||
</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" />
|
||||
</a>
|
||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
||||
@ -40,8 +40,8 @@
|
||||
|
||||
<br/>
|
||||
<p align="center">
|
||||
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=jPq9DsjXs7GUWbXRZU3wygSJyMEy4pqr&jump_from=webapi">
|
||||
<img src="https://img.shields.io/badge/QQ%E7%BE%A4%E2%91%A5-610134978-orange"/></a>
|
||||
<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%A6-715292493-orange"/></a>
|
||||
</p>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
@ -51,7 +51,7 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 📚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;
|
||||
|
||||
@ -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 back-up documentation](https://plus.hutool.cn/docs/#/)
|
||||
|
||||
[📙API](https://apidoc.gitee.com/dromara/hutool/)
|
||||
|
||||
[🎬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:
|
||||
|
||||
👉 [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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 🍐Gradle
|
||||
```
|
||||
implementation 'cn.hutool:hutool-all:5.7.15'
|
||||
implementation 'cn.hutool:hutool-all:5.8.15'
|
||||
```
|
||||
|
||||
## 📥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:
|
||||
> 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
|
||||
|
||||
[](https://giteye.net/chart/GMSL7VDA)
|
||||
|
||||
[](https://starchart.cc/dromara/hutool)
|
||||
|
||||
## 📌WeChat Official Account
|
||||
@ -214,4 +214,4 @@ Hutool welcomes anyone to contribute code to Hutool, but the author suffers from
|
||||
<div align="center">
|
||||
<img src="https://cdn.jsdelivr.net/gh/looly/hutool-site/images/qr_tuling.jpg" height="150">
|
||||
<img src="https://dromara.org/img/qrcode/qrcode_1.png" height="150">
|
||||
</div>
|
||||
</div>
|
||||
|
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">
|
||||
<img src="https://img.shields.io/maven-central/v/cn.hutool/hutool-all.svg?label=Maven%20Central" />
|
||||
</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" />
|
||||
</a>
|
||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
||||
@ -40,8 +40,8 @@
|
||||
|
||||
<br/>
|
||||
<p align="center">
|
||||
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=jPq9DsjXs7GUWbXRZU3wygSJyMEy4pqr&jump_from=webapi">
|
||||
<img src="https://img.shields.io/badge/QQ%E7%BE%A4%E2%91%A5-610134978-orange"/></a>
|
||||
<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%A6-715292493-orange"/></a>
|
||||
</p>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
@ -107,6 +107,8 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
||||
|
||||
[📘中文文档](https://www.hutool.cn/docs/)
|
||||
|
||||
[📘中文备用文档](https://plus.hutool.cn/docs/#/)
|
||||
|
||||
[📙参考API](https://apidoc.gitee.com/dromara/hutool/)
|
||||
|
||||
[🎬视频介绍](https://www.bilibili.com/video/BV1bQ4y1M7d9?p=2)
|
||||
@ -129,7 +131,7 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
||||
|
||||
我们提供了印有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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 🍐Gradle
|
||||
```
|
||||
implementation 'cn.hutool:hutool-all:5.7.15'
|
||||
implementation 'cn.hutool:hutool-all:5.8.15'
|
||||
```
|
||||
|
||||
### 📥下载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平台没有测试,不能保证所有工具类或工具方法可用。
|
||||
@ -209,18 +211,16 @@ Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过维护者是
|
||||
2. Hutool的缩进按照Eclipse(~~不要跟我说IDEA多好用,维护者非常懒,学不会~~,IDEA真香,改了Eclipse快捷键后舒服多了)默认(tab)缩进,所以请遵守(不要和我争执空格与tab的问题,这是一个病人的习惯)。
|
||||
3. 新加的方法不要使用第三方库的方法,Hutool遵循无依赖原则(除非在extra模块中加方法工具)。
|
||||
4. 请pull request到`v5-dev`分支。Hutool在5.x版本后使用了新的分支:`v5-master`是主分支,表示已经发布中央库的版本,这个分支不允许pr,也不允许修改。
|
||||
5. 我们如果关闭了你的issue或pr,请不要诧异,这是我们保持问题处理整洁的一种方式,你依旧可以继续讨论,当有讨论结果时我们会重新打开。
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## ⭐Star Hutool
|
||||
|
||||
[](https://giteye.net/chart/GMSL7VDA)
|
||||
|
||||
[](https://starchart.cc/dromara/hutool)
|
||||
|
||||
## 📌公众号
|
||||
## 📌 知识星球
|
||||
|
||||
<div align="center">
|
||||
<img src="https://cdn.jsdelivr.net/gh/looly/hutool-site/images/qr_tuling.jpg" height="150">
|
||||
<img src="https://dromara.org/img/qrcode/qrcode_1.png" height="150">
|
||||
<img src="https://hutool.cn/images/dromara/zsxq.jpg" height="150">
|
||||
</div>
|
@ -7,5 +7,5 @@ echo ' / /_/ // / / // __// __ \ / __ \ / / '
|
||||
echo ' / __ // /_/ // /_ / /_/ // /_/ // / '
|
||||
echo '/_/ /_/ \____/ \__/ \____/ \____//_/ '
|
||||
echo ''
|
||||
echo '-----------http://hutool.cn/------------'
|
||||
echo '-----------https://hutool.cn/-----------'
|
||||
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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</parent>
|
||||
|
||||
<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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-aop</artifactId>
|
||||
@ -17,9 +17,10 @@
|
||||
<description>Hutool 动态代理(AOP)</description>
|
||||
|
||||
<properties>
|
||||
<Automatic-Module-Name>cn.hutool.aop</Automatic-Module-Name>
|
||||
<!-- versions -->
|
||||
<cglib.version>3.3.0</cglib.version>
|
||||
<spring.version>5.3.10</spring.version>
|
||||
<spring.version>5.3.23</spring.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -43,4 +44,5 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</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
9
hutool-aop/src/main/java/cn/hutool/aop/interceptor/JdkInterceptor.java
Normal file → Executable file
9
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 结束执行回调
|
||||
if (aspect.after(target, method, args, result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// 结束执行回调
|
||||
if (aspect.after(target, method, args, result)) {
|
||||
return result;
|
||||
}
|
||||
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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bloomFilter</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>Hutool 布隆过滤器</description>
|
||||
|
||||
<properties>
|
||||
<Automatic-Module-Name>cn.hutool.bloomfilter</Automatic-Module-Name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
@ -23,4 +27,5 @@
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
4
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BitMapBloomFilter.java
Normal file → Executable file
4
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;
|
||||
|
||||
/**
|
||||
* BlommFilter 实现 <br>
|
||||
* BloomFilter 实现 <br>
|
||||
* 1.构建hash算法 <br>
|
||||
* 2.散列hash映射到数组的bit位置 <br>
|
||||
* 3.验证<br>
|
||||
@ -79,4 +79,4 @@ public class BitMapBloomFilter implements BloomFilter {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BitSetBloomFilter.java
Normal file → Executable file
40
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/BitSetBloomFilter.java
Normal file → Executable file
@ -2,19 +2,21 @@ package cn.hutool.bloomfilter;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HashUtil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.BitSet;
|
||||
|
||||
/**
|
||||
* BloomFilter实现方式2,此方式使用BitSet存储。<br>
|
||||
* Hash算法的使用使用固定顺序,只需指定个数即可
|
||||
* @author loolly
|
||||
*
|
||||
* @author loolly
|
||||
*/
|
||||
public class BitSetBloomFilter implements BloomFilter{
|
||||
public class BitSetBloomFilter implements BloomFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final BitSet bitSet;
|
||||
@ -39,22 +41,36 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
/**
|
||||
* 通过文件初始化过滤器.
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @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 charset 字符集
|
||||
* @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);
|
||||
try {
|
||||
String line;
|
||||
while(true) {
|
||||
while (true) {
|
||||
line = reader.readLine();
|
||||
if(line == null) {
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
this.add(line);
|
||||
}
|
||||
}finally {
|
||||
} finally {
|
||||
IoUtil.close(reader);
|
||||
}
|
||||
}
|
||||
@ -75,6 +91,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
|
||||
/**
|
||||
* 判定是否包含指定字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return 是否包含,存在误差
|
||||
*/
|
||||
@ -101,13 +118,13 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
/**
|
||||
* 将字符串的字节表示进行多哈希编码.
|
||||
*
|
||||
* @param str 待添加进过滤器的字符串字节表示.
|
||||
* @param str 待添加进过滤器的字符串字节表示.
|
||||
* @param hashNumber 要经过的哈希个数.
|
||||
* @return 各个哈希的结果数组.
|
||||
*/
|
||||
public static int[] createHashes(String str, int hashNumber) {
|
||||
int[] result = new int[hashNumber];
|
||||
for(int i = 0; i < hashNumber; i++) {
|
||||
for (int i = 0; i < hashNumber; i++) {
|
||||
result[i] = hash(str, i);
|
||||
|
||||
}
|
||||
@ -116,8 +133,9 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
|
||||
/**
|
||||
* 计算Hash值
|
||||
*
|
||||
* @param str 被计算Hash的字符串
|
||||
* @param k Hash算法序号
|
||||
* @param k Hash算法序号
|
||||
* @return Hash值
|
||||
*/
|
||||
public static int hash(String str, int k) {
|
||||
@ -142,4 +160,4 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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
8
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java
Normal file → Executable file
8
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java
Normal file → Executable file
@ -32,22 +32,22 @@ public class IntMap implements BitMap, Serializable {
|
||||
@Override
|
||||
public void add(long i) {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(long i) {
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(long i) {
|
||||
int r = (int) (i / BitMap.MACHINE32);
|
||||
int c = (int) (i % BitMap.MACHINE32);
|
||||
int c = (int) (i & (BitMap.MACHINE32 - 1));
|
||||
ints[r] &= ~(1 << c);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
8
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java
Normal file → Executable file
8
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java
Normal file → Executable file
@ -32,22 +32,22 @@ public class LongMap implements BitMap, Serializable {
|
||||
@Override
|
||||
public void add(long i) {
|
||||
int r = (int) (i / BitMap.MACHINE64);
|
||||
long c = i % BitMap.MACHINE64;
|
||||
long c = i & (BitMap.MACHINE64 - 1);
|
||||
longs[r] = longs[r] | (1L << c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(long i) {
|
||||
int r = (int) (i / BitMap.MACHINE64);
|
||||
long c = i % BitMap.MACHINE64;
|
||||
long c = i & (BitMap.MACHINE64 - 1);
|
||||
return ((longs[r] >>> c) & 1) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(long i) {
|
||||
int r = (int) (i / BitMap.MACHINE64);
|
||||
long c = i % BitMap.MACHINE64;
|
||||
long c = i & (BitMap.MACHINE64 - 1);
|
||||
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
8
hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java
Normal file → Executable file
8
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 {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected static int DEFAULT_MACHINE_NUM = BitMap.MACHINE32;
|
||||
|
||||
private BitMap bm = null;
|
||||
|
||||
protected long size = 0;
|
||||
protected long size;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -34,7 +36,7 @@ public abstract class AbstractFilter implements BloomFilter {
|
||||
* @param maxValue 最大值
|
||||
*/
|
||||
public AbstractFilter(long maxValue) {
|
||||
this(maxValue, BitMap.MACHINE32);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,4 +82,4 @@ public abstract class AbstractFilter implements BloomFilter {
|
||||
* @return HashCode
|
||||
*/
|
||||
public abstract long hash(String str);
|
||||
}
|
||||
}
|
||||
|
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
|
||||
*/
|
||||
public class DefaultFilter extends AbstractFilter {
|
||||
public class DefaultFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DefaultFilter(long maxValue, int machineNumber) {
|
||||
super(maxValue, machineNumber);
|
||||
}
|
||||
|
||||
public DefaultFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.javaDefaultHash(str) % size;
|
||||
public DefaultFilter(long maxValue, int machineNumber) {
|
||||
super(maxValue, machineNumber, HashUtil::javaDefaultHash);
|
||||
}
|
||||
}
|
||||
|
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;
|
||||
|
||||
public class ELFFilter extends AbstractFilter {
|
||||
public class ELFFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ELFFilter(long maxValue, int machineNumber) {
|
||||
super(maxValue, machineNumber);
|
||||
}
|
||||
|
||||
public ELFFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.elfHash(str) % size;
|
||||
public ELFFilter(long maxValue, int machineNumber) {
|
||||
super(maxValue, machineNumber, HashUtil::elfHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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;
|
||||
|
||||
public class FNVFilter extends AbstractFilter {
|
||||
public class FNVFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FNVFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public FNVFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.fnvHash(str);
|
||||
public FNVFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::fnvHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
||||
public class HfFilter extends AbstractFilter {
|
||||
import cn.hutool.core.util.HashUtil;
|
||||
|
||||
public class HfFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public HfFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public HfFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
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;
|
||||
public HfFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::hfHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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;
|
||||
|
||||
public class HfIpFilter extends AbstractFilter {
|
||||
import cn.hutool.core.util.HashUtil;
|
||||
|
||||
public class HfIpFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public HfIpFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public HfIpFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
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;
|
||||
public HfIpFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::hfIpHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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;
|
||||
|
||||
import cn.hutool.core.util.HashUtil;
|
||||
|
||||
public class JSFilter extends AbstractFilter {
|
||||
public class JSFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public JSFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public JSFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
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;
|
||||
public JSFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::jsHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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;
|
||||
|
||||
public class PJWFilter extends AbstractFilter {
|
||||
public class PJWFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public PJWFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public PJWFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.pjwHash(str) % size;
|
||||
public PJWFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::pjwHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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;
|
||||
|
||||
public class RSFilter extends AbstractFilter {
|
||||
public class RSFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RSFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public RSFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.rsHash(str) % size;
|
||||
public RSFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::rsHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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;
|
||||
|
||||
public class SDBMFilter extends AbstractFilter {
|
||||
public class SDBMFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SDBMFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public SDBMFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.sdbmHash(str) % size;
|
||||
public SDBMFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::sdbmHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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;
|
||||
|
||||
|
||||
public class TianlFilter extends AbstractFilter {
|
||||
public class TianlFilter extends FuncFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public TianlFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
public TianlFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
this(maxValue, DEFAULT_MACHINE_NUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.tianlHash(str) % size;
|
||||
public TianlFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum, HashUtil::tianlHash);
|
||||
}
|
||||
|
||||
}
|
||||
|
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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</parent>
|
||||
|
||||
<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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cache</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>Hutool 缓存</description>
|
||||
|
||||
<properties>
|
||||
<Automatic-Module-Name>cn.hutool.cache</Automatic-Module-Name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<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.CacheListener;
|
||||
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.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 超时和限制大小的缓存的默认实现<br>
|
||||
@ -27,12 +30,12 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected Map<K, CacheObj<K, V>> cacheMap;
|
||||
protected Map<Mutable<K>, CacheObj<K, V>> cacheMap;
|
||||
|
||||
/**
|
||||
* 写的时候每个key一把锁,降低锁的粒度
|
||||
*/
|
||||
protected final Map<K, Lock> keyLockMap = new ConcurrentHashMap<>();
|
||||
protected final SafeConcurrentHashMap<K, Lock> keyLockMap = new SafeConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 返回缓存容量,{@code 0}表示无大小限制
|
||||
@ -84,7 +87,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
if (isFull()) {
|
||||
pruneCache();
|
||||
}
|
||||
cacheMap.put(key, co);
|
||||
cacheMap.put(MutableObj.of(key), co);
|
||||
}
|
||||
// ---------------------------------------------------------------- put end
|
||||
|
||||
@ -112,7 +115,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
keyLock.lock();
|
||||
try {
|
||||
// 双重检查锁,防止在竞争锁的过程中已经有其它线程写入
|
||||
final CacheObj<K, V> co = cacheMap.get(key);
|
||||
final CacheObj<K, V> co = getWithoutLock(key);
|
||||
if (null == co || co.isExpired()) {
|
||||
try {
|
||||
v = supplier.call();
|
||||
@ -130,6 +133,16 @@ public abstract class AbstractCache<K, V> implements Cache<K, 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
|
||||
|
||||
@Override
|
||||
@ -212,7 +225,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
* @since 5.5.9
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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) {
|
||||
// 在丢失计数有效的情况下,移除一般为get时的超时操作,此处应该丢失数+1
|
||||
this.missCount.increment();
|
||||
}
|
||||
return co;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有{@link CacheObj}值的{@link Iterator}形式
|
||||
* @return {@link Iterator}
|
||||
* @since 5.8.0
|
||||
*/
|
||||
protected Iterator<CacheObj<K, V>> cacheObjIter(){
|
||||
return this.cacheMap.values().iterator();
|
||||
}
|
||||
}
|
||||
|
62
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java
vendored
Normal file → Executable file
62
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java
vendored
Normal file → Executable file
@ -1,27 +1,36 @@
|
||||
package cn.hutool.cache.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* 缓存对象
|
||||
* @author Looly
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @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;
|
||||
|
||||
protected final K key;
|
||||
protected final V obj;
|
||||
|
||||
/** 上次访问时间 */
|
||||
private volatile long lastAccess;
|
||||
/** 访问次数 */
|
||||
/**
|
||||
* 上次访问时间
|
||||
*/
|
||||
protected volatile long lastAccess;
|
||||
/**
|
||||
* 访问次数
|
||||
*/
|
||||
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 键
|
||||
* @since 4.0.10
|
||||
*/
|
||||
@ -48,6 +58,7 @@ public class CacheObj<K, V> implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
* @return 值
|
||||
* @since 4.0.10
|
||||
*/
|
||||
@ -55,6 +66,39 @@ public class CacheObj<K, V> implements Serializable{
|
||||
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
|
||||
public String toString() {
|
||||
return "CacheObj [key=" + key + ", obj=" + obj + ", lastAccess=" + lastAccess + ", accessCount=" + accessCount + ", ttl=" + ttl + "]";
|
||||
@ -66,7 +110,7 @@ public class CacheObj<K, V> implements Serializable{
|
||||
* @return 是否过期
|
||||
*/
|
||||
protected boolean isExpired() {
|
||||
if(this.ttl > 0) {
|
||||
if (this.ttl > 0) {
|
||||
// 此处不考虑时间回拨
|
||||
return (System.currentTimeMillis() - this.lastAccess) > this.ttl;
|
||||
}
|
||||
@ -81,7 +125,7 @@ public class CacheObj<K, V> implements Serializable{
|
||||
* @since 4.0.10
|
||||
*/
|
||||
protected V get(boolean isUpdateLastAccess) {
|
||||
if(isUpdateLastAccess) {
|
||||
if (isUpdateLastAccess) {
|
||||
lastAccess = System.currentTimeMillis();
|
||||
}
|
||||
accessCount.getAndIncrement();
|
||||
|
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;
|
||||
|
||||
// 清理过期对象并找出链表头部元素(先入元素)
|
||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
||||
final Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||
if (isPruneExpiredActive()) {
|
||||
// 清理过期对象并找出链表头部元素(先入元素)
|
||||
while (values.hasNext()) {
|
||||
@ -71,7 +71,7 @@ public class FIFOCache<K, V> extends StampedCache<K, V> {
|
||||
|
||||
// 清理结束后依旧是满的,则删除第一个被缓存的对象
|
||||
if (isFull() && null != first) {
|
||||
cacheMap.remove(first.key);
|
||||
removeWithoutLock(first.key, false);
|
||||
onRemove(first.key, first.obj);
|
||||
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;
|
||||
|
||||
// 清理过期对象并找出访问最少的对象
|
||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
||||
Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||
CacheObj<K, V> co;
|
||||
while (values.hasNext()) {
|
||||
co = values.next();
|
||||
@ -78,7 +78,7 @@ public class LFUCache<K, V> extends StampedCache<K, V> {
|
||||
if (isFull() && comin != null) {
|
||||
long minAccessCount = comin.accessCount.get();
|
||||
|
||||
values = cacheMap.values().iterator();
|
||||
values = cacheObjIter();
|
||||
CacheObj<K, V> co1;
|
||||
while (values.hasNext()) {
|
||||
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;
|
||||
|
||||
import cn.hutool.core.lang.mutable.Mutable;
|
||||
import cn.hutool.core.map.FixedLinkedHashMap;
|
||||
|
||||
import java.util.Iterator;
|
||||
@ -42,7 +43,13 @@ public class LRUCache<K, V> extends ReentrantCache<K, V> {
|
||||
this.timeout = timeout;
|
||||
|
||||
//链表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
|
||||
@ -56,7 +63,7 @@ public class LRUCache<K, V> extends ReentrantCache<K, V> {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
||||
Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||
CacheObj<K, V> co;
|
||||
while (values.hasNext()) {
|
||||
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;
|
||||
|
||||
// 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
|
||||
// 最优的解决方案是使用Guava的ConcurrentLinkedHashMap,此处使用简化的互斥锁
|
||||
// TODO 最优的解决方案是使用Guava的ConcurrentLinkedHashMap,此处使用简化的互斥锁
|
||||
protected final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
@ -36,7 +36,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
||||
lock.lock();
|
||||
try {
|
||||
// 不存在或已移除
|
||||
final CacheObj<K, V> co = cacheMap.get(key);
|
||||
final CacheObj<K, V> co = getWithoutLock(key);
|
||||
if (co == null) {
|
||||
return false;
|
||||
}
|
||||
@ -59,7 +59,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
||||
CacheObj<K, V> co;
|
||||
lock.lock();
|
||||
try {
|
||||
co = cacheMap.get(key);
|
||||
co = getWithoutLock(key);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@ -83,7 +83,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
||||
CopiedIter<CacheObj<K, V>> copiedIterator;
|
||||
lock.lock();
|
||||
try {
|
||||
copiedIterator = CopiedIter.copyOf(this.cacheMap.values().iterator());
|
||||
copiedIterator = CopiedIter.copyOf(cacheObjIter());
|
||||
} finally {
|
||||
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对应的对象
|
||||
*
|
||||
|
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();
|
||||
try {
|
||||
// 不存在或已移除
|
||||
final CacheObj<K, V> co = cacheMap.get(key);
|
||||
final CacheObj<K, V> co = getWithoutLock(key);
|
||||
if (co == null) {
|
||||
return false;
|
||||
}
|
||||
@ -58,12 +58,12 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
||||
public V get(K key, boolean isUpdateLastAccess) {
|
||||
// 尝试读取缓存,使用乐观读锁
|
||||
long stamp = lock.tryOptimisticRead();
|
||||
CacheObj<K, V> co = cacheMap.get(key);
|
||||
CacheObj<K, V> co = getWithoutLock(key);
|
||||
if(false == lock.validate(stamp)){
|
||||
// 有写线程修改了此对象,悲观读
|
||||
stamp = lock.readLock();
|
||||
try {
|
||||
co = cacheMap.get(key);
|
||||
co = getWithoutLock(key);
|
||||
} finally {
|
||||
lock.unlockRead(stamp);
|
||||
}
|
||||
@ -88,7 +88,7 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
||||
CopiedIter<CacheObj<K, V>> copiedIterator;
|
||||
final long stamp = lock.readLock();
|
||||
try {
|
||||
copiedIterator = CopiedIter.copyOf(this.cacheMap.values().iterator());
|
||||
copiedIterator = CopiedIter.copyOf(cacheObjIter());
|
||||
} finally {
|
||||
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;
|
||||
|
||||
import cn.hutool.cache.GlobalPruneTimer;
|
||||
import cn.hutool.core.lang.mutable.Mutable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@ -37,7 +38,7 @@ public class TimedCache<K, V> extends StampedCache<K, V> {
|
||||
* @param timeout 过期时长
|
||||
* @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.timeout = timeout;
|
||||
this.cacheMap = map;
|
||||
@ -52,7 +53,7 @@ public class TimedCache<K, V> extends StampedCache<K, V> {
|
||||
@Override
|
||||
protected int pruneCache() {
|
||||
int count = 0;
|
||||
Iterator<CacheObj<K, V>> values = cacheMap.values().iterator();
|
||||
final Iterator<CacheObj<K, V>> values = cacheObjIter();
|
||||
CacheObj<K, V> co;
|
||||
while (values.hasNext()) {
|
||||
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;
|
||||
|
||||
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>
|
||||
@ -17,8 +22,22 @@ import java.util.WeakHashMap;
|
||||
public class WeakCache<K, V> extends TimedCache<K, V>{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param timeout 超时时常,单位毫秒,-1或0表示无限制
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lfuCacheTest2(){
|
||||
Cache<String, String> lfuCache = CacheUtil.newLFUCache(3);
|
||||
final String s = lfuCache.get(null);
|
||||
Assert.assertNull(s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lruCacheTest(){
|
||||
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;
|
||||
|
||||
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.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 见:https://github.com/dromara/hutool/issues/1895<br>
|
||||
@ -13,17 +18,29 @@ import java.util.concurrent.CountDownLatch;
|
||||
*/
|
||||
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
|
||||
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++) {
|
||||
cache.put(i, i);
|
||||
}
|
||||
|
||||
CountDownLatch countDownLatch = new CountDownLatch(10);
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(10);
|
||||
// 10个线程分别读0-9 10000次
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int finalI = i;
|
||||
final int finalI = i;
|
||||
new Thread(() -> {
|
||||
for (int j = 0; j < 10000; j++) {
|
||||
cache.get(finalI);
|
||||
@ -34,7 +51,7 @@ public class LRUCacheTest {
|
||||
// 等待读线程结束
|
||||
countDownLatch.await();
|
||||
// 按顺序读0-9
|
||||
StringBuilder sb1 = new StringBuilder();
|
||||
final StringBuilder sb1 = new StringBuilder();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
sb1.append(cache.get(i));
|
||||
}
|
||||
@ -43,10 +60,29 @@ public class LRUCacheTest {
|
||||
// 新加11,此时0最久未使用,应该淘汰0
|
||||
cache.put(11, 11);
|
||||
|
||||
StringBuilder sb2 = new StringBuilder();
|
||||
final StringBuilder sb2 = new StringBuilder();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
sb2.append(cache.get(i));
|
||||
}
|
||||
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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-captcha</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>Hutool 验证码工具</description>
|
||||
|
||||
<properties>
|
||||
<Automatic-Module-Name>cn.hutool.captcha</Automatic-Module-Name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
@ -23,4 +27,5 @@
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</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>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.7.15</version>
|
||||
<version>5.8.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-core</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>Hutool核心,包括集合、字符串、Bean等工具</description>
|
||||
|
||||
<properties>
|
||||
<Automatic-Module-Name>cn.hutool.core</Automatic-Module-Name>
|
||||
</properties>
|
||||
</project>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user