mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
Merge remote-tracking branch 'upstream/v5-dev' into v5-dev
This commit is contained in:
commit
bb5b524418
30
CHANGELOG.md
30
CHANGELOG.md
@ -3,17 +3,45 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.5.9 (2021-02-18)
|
||||
# 5.6.0 (2021-03-10)
|
||||
|
||||
### 新特性
|
||||
* 【poi 】 重要:不再兼容POI-3.x,增加兼容POI-5.x(issue#I35J6B@Gitee)
|
||||
* 【core 】 FileTypeUtil使用长匹配优先(pr#1457@Github)
|
||||
* 【core 】 IterUtil和CollUtil增加isEqualList方法(issue#I3A3PY@Gitee)
|
||||
* 【crypto 】 增加PBKDF2(issue#1416@Github)
|
||||
* 【core 】 增加FuncKeyMap(issue#1402@Github)
|
||||
* 【core 】 增加StrMatcher(issue#1379@Github)
|
||||
* 【core 】 NumberUtil增加factorial针对BigInterger方法(issue#1379@Github)
|
||||
* 【core 】 TreeNode增加equals方法(issue#1467@Github)
|
||||
|
||||
### Bug修复
|
||||
* 【socket 】 修复Client创建失败资源未释放问题。
|
||||
* 【core 】 修复DataSizeUtil中EB单位错误问题(issue#I39O7I@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.5.9 (2021-02-26)
|
||||
|
||||
### 新特性
|
||||
* 【crypto 】 PemUtil.readPemKey支持EC(pr#1366@Github)
|
||||
* 【extra 】 Ftp等cd方法增加同步(issue#1397@Github)
|
||||
* 【core 】 StrUtil增加endWithAnyIgnoreCase(issue#I37I0B@Gitee)
|
||||
* 【crypto 】 Sm2增加getD和getQ方法(issue#I37Z4C@Gitee)
|
||||
* 【cache 】 AbstractCache增加keySet方法(issue#I37Z4C@Gitee)
|
||||
* 【core 】 NumberWordFormatter增加formatSimple方法(pr#1436@Github)
|
||||
* 【crypto 】 增加读取openSSL生成的sm2私钥
|
||||
* 【crypto 】 增加众多方法,SM2兼容各类密钥格式(issue#I37Z75@Gitee)
|
||||
|
||||
### Bug修复
|
||||
* 【json 】 JSONUtil.isJson方法改变trim策略,解决特殊空白符导致判断失败问题
|
||||
* 【json 】 修复SQLEXception导致的栈溢出(issue#1399@Github)
|
||||
* 【extra 】 修复Ftp中异常参数没有传入问题(issue#1397@Github)
|
||||
* 【crypto 】 修复Sm2使用D构造空指针问题(issue#I37Z4C@Gitee)
|
||||
* 【poi 】 修复ExcelPicUtil中图表报错问题(issue#I38857@Gitee)
|
||||
* 【core 】 修复ListUtil.page方法返回空列表无法编辑问题(issue#1415@Github)
|
||||
* 【core 】 修复ListUtil.sub中step不通结果不一致问题(issue#1409@Github)
|
||||
* 【db 】 修复Condition转换参数值时未转换数字异常(issue#I38LTM@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -125,19 +125,19 @@ Each module can be introduced individually, or all modules can be introduced by
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.5.9</version>
|
||||
<version>5.6.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### Gradle
|
||||
```
|
||||
compile 'cn.hutool:hutool-all:5.5.9'
|
||||
compile 'cn.hutool:hutool-all:5.6.0'
|
||||
```
|
||||
|
||||
## Download
|
||||
|
||||
- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.9/)
|
||||
- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.9/)
|
||||
- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.6.0/)
|
||||
- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.6.0/)
|
||||
|
||||
> 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.
|
||||
|
@ -123,21 +123,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.5.9</version>
|
||||
<version>5.6.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### Gradle
|
||||
```
|
||||
compile 'cn.hutool:hutool-all:5.5.9'
|
||||
compile 'cn.hutool:hutool-all:5.6.0'
|
||||
```
|
||||
|
||||
### 非Maven项目
|
||||
|
||||
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
|
||||
|
||||
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.9/)
|
||||
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.9/)
|
||||
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.6.0/)
|
||||
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.6.0/)
|
||||
|
||||
> 注意
|
||||
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
||||
|
@ -1 +1 @@
|
||||
5.5.9
|
||||
5.6.0
|
||||
|
@ -1 +1 @@
|
||||
var version = '5.5.9'
|
||||
var version = '5.6.0'
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.5.9-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-all</artifactId>
|
||||
|
@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Hutool是Hu + tool的自造词,前者致敬我的“前任公司”,后者为工具之意,谐音“糊涂”,寓意追求“万事都作糊涂观,无所谓失,无所谓得”的境界。
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以“甜甜的”。<br>
|
||||
* Hutool最初是我项目中“util”包的一个整理,后来慢慢积累并加入更多非业务相关功能,并广泛学习其它开源项目精髓,经过自己整理修改,最终形成丰富的开源工具集。
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.5.9-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-aop</artifactId>
|
||||
|
@ -13,10 +13,10 @@ import cn.hutool.core.util.ClassUtil;
|
||||
*
|
||||
*/
|
||||
public final class ProxyUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 使用切面代理对象
|
||||
*
|
||||
*
|
||||
* @param <T> 切面对象类型
|
||||
* @param target 目标对象
|
||||
* @param aspectClass 切面对象类
|
||||
@ -25,10 +25,10 @@ public final class ProxyUtil {
|
||||
public static <T> T proxy(T target, Class<? extends Aspect> aspectClass){
|
||||
return ProxyFactory.createProxy(target, aspectClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 使用切面代理对象
|
||||
*
|
||||
*
|
||||
* @param <T> 被代理对象类型
|
||||
* @param target 被代理对象
|
||||
* @param aspect 切面对象
|
||||
@ -47,8 +47,8 @@ public final class ProxyUtil {
|
||||
* 3、调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,这些实现方法的实现本质上是通过反射调用被代理对象的方法<br>
|
||||
* 4、将$Proxy0的实例返回给客户端。 <br>
|
||||
* 5、当调用代理类的相应方法时,相当于调用 {@link InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])} 方法
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param <T> 被代理对象类型
|
||||
* @param classloader 被代理类对应的ClassLoader
|
||||
* @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能
|
||||
@ -59,10 +59,10 @@ public final class ProxyUtil {
|
||||
public static <T> T newProxyInstance(ClassLoader classloader, InvocationHandler invocationHandler, Class<?>... interfaces) {
|
||||
return (T) Proxy.newProxyInstance(classloader, interfaces, invocationHandler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建动态代理对象
|
||||
*
|
||||
*
|
||||
* @param <T> 被代理对象类型
|
||||
* @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能
|
||||
* @param interfaces 代理类中需要实现的被代理类的接口方法
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 切面实现,提供一些基本的切面实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 代理拦截器实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* JDK动态代理封装,提供非IOC下的切面支持
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@ import net.sf.cglib.proxy.Enhancer;
|
||||
|
||||
/**
|
||||
* 基于Cglib的切面代理工厂
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@ import org.springframework.cglib.proxy.Enhancer;
|
||||
|
||||
/**
|
||||
* 基于Spring-cglib的切面代理工厂
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 代理实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.5.9-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bloomFilter</artifactId>
|
||||
|
@ -16,7 +16,7 @@ import java.util.BitSet;
|
||||
*/
|
||||
public class BitSetBloomFilter implements BloomFilter{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final BitSet bitSet;
|
||||
private final int bitSetSize;
|
||||
private final int addedElements;
|
||||
@ -24,7 +24,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
|
||||
/**
|
||||
* 构造一个布隆过滤器,过滤器的容量为c * n 个bit.
|
||||
*
|
||||
*
|
||||
* @param c 当前过滤器预先开辟的最大包含记录,通常要比预计存入的记录多一倍.
|
||||
* @param n 当前过滤器预计所要包含的记录.
|
||||
* @param k 哈希函数的个数,等同每条记录要占用的bit数.
|
||||
@ -38,7 +38,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
|
||||
/**
|
||||
* 通过文件初始化过滤器.
|
||||
*
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param charset 字符集
|
||||
* @throws IOException IO异常
|
||||
@ -58,7 +58,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
IoUtil.close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean add(String str) {
|
||||
if (contains(str)) {
|
||||
@ -72,7 +72,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判定是否包含指定字符串
|
||||
* @param str 字符串
|
||||
@ -89,7 +89,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return 得到当前过滤器的错误率.
|
||||
*/
|
||||
@ -100,7 +100,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
|
||||
/**
|
||||
* 将字符串的字节表示进行多哈希编码.
|
||||
*
|
||||
*
|
||||
* @param str 待添加进过滤器的字符串字节表示.
|
||||
* @param hashNumber 要经过的哈希个数.
|
||||
* @return 各个哈希的结果数组.
|
||||
@ -109,7 +109,7 @@ public class BitSetBloomFilter implements BloomFilter{
|
||||
int[] result = new int[hashNumber];
|
||||
for(int i = 0; i < hashNumber; i++) {
|
||||
result[i] = hash(str, i);
|
||||
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import java.io.Serializable;
|
||||
public interface BloomFilter extends Serializable{
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return 判断一个字符串是否bitMap中存在
|
||||
*/
|
||||
@ -21,7 +21,7 @@ public interface BloomFilter extends Serializable{
|
||||
/**
|
||||
* 在boolean的bitMap中增加一个字符串<br>
|
||||
* 如果存在就返回<code>false</code> .如果不存在.先增加这个字符串.再返回<code>true</code>
|
||||
*
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return 是否加入成功,如果存在就返回<code>false</code> .如果不存在返回<code>true</code>
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@ package cn.hutool.bloomfilter;
|
||||
|
||||
/**
|
||||
* 布隆过滤器工具
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.5
|
||||
*/
|
||||
@ -10,7 +10,7 @@ public class BloomFilterUtil {
|
||||
|
||||
/**
|
||||
* 创建一个BitSet实现的布隆过滤器,过滤器的容量为c * n 个bit.
|
||||
*
|
||||
*
|
||||
* @param c 当前过滤器预先开辟的最大包含记录,通常要比预计存入的记录多一倍.
|
||||
* @param n 当前过滤器预计所要包含的记录.
|
||||
* @param k 哈希函数的个数,等同每条记录要占用的bit数.
|
||||
@ -22,7 +22,7 @@ public class BloomFilterUtil {
|
||||
|
||||
/**
|
||||
* 创建BitMap实现的布隆过滤器
|
||||
*
|
||||
*
|
||||
* @param m BitMap的大小
|
||||
* @return BitMapBloomFilter
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@ package cn.hutool.bloomfilter.bitMap;
|
||||
|
||||
/**
|
||||
* BitMap接口,用于将某个int或long值映射到一个数组中,从而判定某个值是否存在
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
@ -13,14 +13,14 @@ public interface BitMap{
|
||||
|
||||
/**
|
||||
* 加入值
|
||||
*
|
||||
*
|
||||
* @param i 值
|
||||
*/
|
||||
void add(long i);
|
||||
|
||||
/**
|
||||
* 检查是否包含值
|
||||
*
|
||||
*
|
||||
* @param i 值
|
||||
* @return 是否包含
|
||||
*/
|
||||
@ -28,7 +28,7 @@ public interface BitMap{
|
||||
|
||||
/**
|
||||
* 移除值
|
||||
*
|
||||
*
|
||||
* @param i 值
|
||||
*/
|
||||
void remove(long i);
|
||||
|
@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 过滤器BitMap在32位机器上.这个类能发生更好的效果.一般情况下建议使用此类
|
||||
*
|
||||
*
|
||||
* @author loolly
|
||||
*
|
||||
*/
|
||||
@ -22,7 +22,7 @@ public class IntMap implements BitMap, Serializable {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param size 容量
|
||||
*/
|
||||
public IntMap(int size) {
|
||||
|
@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 过滤器BitMap在64位机器上.这个类能发生更好的效果.一般机器不建议使用
|
||||
*
|
||||
*
|
||||
* @author loolly
|
||||
*
|
||||
*/
|
||||
@ -22,7 +22,7 @@ public class LongMap implements BitMap, Serializable {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param size 容量
|
||||
*/
|
||||
public LongMap(int size) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* BitMap实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@ import cn.hutool.bloomfilter.bitMap.LongMap;
|
||||
|
||||
/**
|
||||
* 抽象Bloom过滤器
|
||||
*
|
||||
*
|
||||
* @author loolly
|
||||
*
|
||||
*/
|
||||
@ -20,7 +20,7 @@ public abstract class AbstractFilter implements BloomFilter {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param maxValue 最大值
|
||||
* @param machineNum 机器位数
|
||||
*/
|
||||
@ -30,7 +30,7 @@ public abstract class AbstractFilter implements BloomFilter {
|
||||
|
||||
/**
|
||||
* 构造32位
|
||||
*
|
||||
*
|
||||
* @param maxValue 最大值
|
||||
*/
|
||||
public AbstractFilter(long maxValue) {
|
||||
@ -39,7 +39,7 @@ public abstract class AbstractFilter implements BloomFilter {
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
*
|
||||
* @param maxValue 最大值
|
||||
* @param machineNum 机器位数
|
||||
*/
|
||||
@ -75,7 +75,7 @@ public abstract class AbstractFilter implements BloomFilter {
|
||||
|
||||
/**
|
||||
* 自定义Hash方法
|
||||
*
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return HashCode
|
||||
*/
|
||||
|
@ -8,11 +8,11 @@ public class ELFFilter extends AbstractFilter {
|
||||
public ELFFilter(long maxValue, int machineNumber) {
|
||||
super(maxValue, machineNumber);
|
||||
}
|
||||
|
||||
|
||||
public ELFFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
return HashUtil.elfHash(str) % size;
|
||||
|
@ -7,11 +7,11 @@ public class HfFilter extends AbstractFilter {
|
||||
public HfFilter(long maxValue, int machineNum) {
|
||||
super(maxValue, machineNum);
|
||||
}
|
||||
|
||||
|
||||
public HfFilter(long maxValue) {
|
||||
super(maxValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long hash(String str) {
|
||||
int length = str.length() ;
|
||||
|
@ -19,11 +19,11 @@ public class JSFilter extends AbstractFilter {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2));
|
||||
}
|
||||
|
||||
|
||||
if(hash<0) {
|
||||
hash*=-1 ;
|
||||
}
|
||||
|
||||
|
||||
return hash % size;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 各种Hash算法的过滤器实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 布隆过滤,提供一些Hash算法的布隆过滤
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -8,14 +8,14 @@ import cn.hutool.bloomfilter.bitMap.IntMap;
|
||||
import cn.hutool.bloomfilter.bitMap.LongMap;
|
||||
|
||||
public class BitMapBloomFilterTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void filterTest() {
|
||||
BitMapBloomFilter filter = new BitMapBloomFilter(10);
|
||||
filter.add("123");
|
||||
filter.add("abc");
|
||||
filter.add("ddd");
|
||||
|
||||
|
||||
Assert.assertTrue(filter.contains("abc"));
|
||||
Assert.assertTrue(filter.contains("ddd"));
|
||||
Assert.assertTrue(filter.contains("123"));
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.5.9-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bom</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.5.9-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cache</artifactId>
|
||||
|
@ -13,10 +13,10 @@ import cn.hutool.cache.impl.WeakCache;
|
||||
*@since 3.0.1
|
||||
*/
|
||||
public class CacheUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 创建FIFO(first in first out) 先进先出缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param capacity 容量
|
||||
@ -26,10 +26,10 @@ public class CacheUtil {
|
||||
public static <K, V> FIFOCache<K, V> newFIFOCache(int capacity, long timeout){
|
||||
return new FIFOCache<>(capacity, timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建FIFO(first in first out) 先进先出缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param capacity 容量
|
||||
@ -38,10 +38,10 @@ public class CacheUtil {
|
||||
public static <K, V> FIFOCache<K, V> newFIFOCache(int capacity){
|
||||
return new FIFOCache<>(capacity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建LFU(least frequently used) 最少使用率缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param capacity 容量
|
||||
@ -51,10 +51,10 @@ public class CacheUtil {
|
||||
public static <K, V> LFUCache<K, V> newLFUCache(int capacity, long timeout){
|
||||
return new LFUCache<>(capacity, timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建LFU(least frequently used) 最少使用率缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param capacity 容量
|
||||
@ -63,11 +63,11 @@ public class CacheUtil {
|
||||
public static <K, V> LFUCache<K, V> newLFUCache(int capacity){
|
||||
return new LFUCache<>(capacity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建LRU (least recently used)最近最久未使用缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param capacity 容量
|
||||
@ -77,10 +77,10 @@ public class CacheUtil {
|
||||
public static <K, V> LRUCache<K, V> newLRUCache(int capacity, long timeout){
|
||||
return new LRUCache<>(capacity, timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建LRU (least recently used)最近最久未使用缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param capacity 容量
|
||||
@ -89,10 +89,10 @@ public class CacheUtil {
|
||||
public static <K, V> LRUCache<K, V> newLRUCache(int capacity){
|
||||
return new LRUCache<>(capacity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建定时缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param timeout 过期时长,单位:毫秒
|
||||
@ -101,10 +101,10 @@ public class CacheUtil {
|
||||
public static <K, V> TimedCache<K, V> newTimedCache(long timeout){
|
||||
return new TimedCache<>(timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建弱引用缓存.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @param timeout 过期时长,单位:毫秒
|
||||
@ -114,10 +114,10 @@ public class CacheUtil {
|
||||
public static <K, V> WeakCache<K, V> newWeakCache(long timeout){
|
||||
return new WeakCache<>(timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建无缓存实现.
|
||||
*
|
||||
*
|
||||
* @param <K> Key类型
|
||||
* @param <V> Value类型
|
||||
* @return {@link NoCache}
|
||||
|
@ -23,7 +23,7 @@ public abstract class AbstractFileCache implements Serializable{
|
||||
protected final long timeout;
|
||||
/** 缓存实现 */
|
||||
protected final Cache<File, byte[]> cache;
|
||||
|
||||
|
||||
/** 已使用缓存空间 */
|
||||
protected int usedSize;
|
||||
|
||||
@ -122,7 +122,7 @@ public abstract class AbstractFileCache implements Serializable{
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------- protected method start
|
||||
/**
|
||||
* 初始化实现文件缓存的缓存对象
|
||||
|
@ -12,7 +12,7 @@ import cn.hutool.cache.impl.LFUCache;
|
||||
*/
|
||||
public class LFUFileCache extends AbstractFileCache{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* 构造<br>
|
||||
* 最大文件大小为缓存容量的一半<br>
|
||||
|
@ -12,7 +12,7 @@ import cn.hutool.cache.impl.LRUCache;
|
||||
*/
|
||||
public class LRUFileCache extends AbstractFileCache{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* 构造<br>
|
||||
* 最大文件大小为缓存容量的一半<br>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 提供针对文件的缓存实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -7,6 +7,7 @@ import cn.hutool.core.lang.func.Func0;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@ -307,11 +308,22 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
* @return this
|
||||
* @since 5.5.2
|
||||
*/
|
||||
@Override
|
||||
public AbstractCache<K, V> setListener(CacheListener<K, V> listener) {
|
||||
this.listener = listener;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回所有键
|
||||
*
|
||||
* @return 所有键
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public Set<K> keySet(){
|
||||
return this.cacheMap.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象移除回调。默认无动作<br>
|
||||
* 子类可重写此方法用于监听移除事件,如果重写,listener将无效
|
||||
|
@ -12,20 +12,20 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
*/
|
||||
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 AtomicLong accessCount = new AtomicLong();
|
||||
/** 对象存活时长,0表示永久存活*/
|
||||
private final long ttl;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param key 键
|
||||
* @param obj 值
|
||||
* @param ttl 超时时长
|
||||
@ -36,10 +36,10 @@ public class CacheObj<K, V> implements Serializable{
|
||||
this.ttl = ttl;
|
||||
this.lastAccess = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断是否过期
|
||||
*
|
||||
*
|
||||
* @return 是否过期
|
||||
*/
|
||||
boolean isExpired() {
|
||||
@ -49,10 +49,10 @@ public class CacheObj<K, V> implements Serializable{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
*
|
||||
* @param isUpdateLastAccess 是否更新最后访问时间
|
||||
* @return 获得对象
|
||||
* @since 4.0.10
|
||||
@ -64,7 +64,7 @@ public class CacheObj<K, V> implements Serializable{
|
||||
accessCount.getAndIncrement();
|
||||
return this.obj;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取键
|
||||
* @return 键
|
||||
@ -73,7 +73,7 @@ public class CacheObj<K, V> implements Serializable{
|
||||
public K getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
* @return 值
|
||||
@ -82,7 +82,7 @@ public class CacheObj<K, V> implements Serializable{
|
||||
public V getValue() {
|
||||
return this.obj;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CacheObj [key=" + key + ", obj=" + obj + ", lastAccess=" + lastAccess + ", accessCount=" + accessCount + ", ttl=" + ttl + "]";
|
||||
|
@ -6,7 +6,7 @@ import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* {@link cn.hutool.cache.impl.AbstractCache} 的CacheObj迭代器.
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
* @param <K> 键类型
|
||||
@ -21,7 +21,7 @@ public class CacheObjIterator<K, V> implements Iterator<CacheObj<K, V>>, Seriali
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param iterator 原{@link Iterator}
|
||||
*/
|
||||
CacheObjIterator(Iterator<CacheObj<K, V>> iterator) {
|
||||
|
@ -48,7 +48,7 @@ public class LRUCache<K, V> extends AbstractCache<K, V> {
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/**
|
||||
* 只清理超时对象,LRU的实现会交给<code>LinkedHashMap</code>
|
||||
* 只清理超时对象,LRU的实现会交给{@code LinkedHashMap}
|
||||
*/
|
||||
@Override
|
||||
protected int pruneCache() {
|
||||
|
@ -7,7 +7,7 @@ import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* 无缓存实现,用于快速关闭缓存
|
||||
*
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @author Looly,jodd
|
||||
@ -49,7 +49,7 @@ public class NoCache<K, V> implements Cache<K, V> {
|
||||
public V get(K key, boolean isUpdateLastAccess) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public V get(K key, Func0<V> supplier) {
|
||||
return get(key, true, supplier);
|
||||
@ -78,7 +78,7 @@ public class NoCache<K, V> implements Cache<K, V> {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<CacheObj<K, V>> cacheObjIterator() {
|
||||
return null;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 提供各种缓存实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 提供简易的缓存实现,此模块参考了jodd工具中的Cache模块
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -14,7 +14,7 @@ import org.junit.Test;
|
||||
*
|
||||
*/
|
||||
public class CacheTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void fifoCacheTest(){
|
||||
Cache<String,String> fifoCache = CacheUtil.newFIFOCache(3);
|
||||
@ -28,22 +28,22 @@ public class CacheTest {
|
||||
fifoCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
|
||||
fifoCache.put("key3", "value3", DateUnit.SECOND.getMillis() * 3);
|
||||
fifoCache.put("key4", "value4", DateUnit.SECOND.getMillis() * 3);
|
||||
|
||||
|
||||
//由于缓存容量只有3,当加入第四个元素的时候,根据FIFO规则,最先放入的对象将被移除
|
||||
String value1 = fifoCache.get("key1");
|
||||
Assert.assertNull(value1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void lfuCacheTest(){
|
||||
Cache<String, String> lfuCache = CacheUtil.newLFUCache(3);
|
||||
lfuCache.put("key1", "value1", DateUnit.SECOND.getMillis() * 3);
|
||||
//使用次数+1
|
||||
lfuCache.get("key1");
|
||||
lfuCache.get("key1");
|
||||
lfuCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
|
||||
lfuCache.put("key3", "value3", DateUnit.SECOND.getMillis() * 3);
|
||||
lfuCache.put("key4", "value4", DateUnit.SECOND.getMillis() * 3);
|
||||
|
||||
|
||||
//由于缓存容量只有3,当加入第四个元素的时候,根据LFU规则,最少使用的将被移除(2,3被移除)
|
||||
String value1 = lfuCache.get("key1");
|
||||
String value2 = lfuCache.get("key2");
|
||||
@ -52,7 +52,7 @@ public class CacheTest {
|
||||
Assert.assertNull(value2);
|
||||
Assert.assertNull(value3);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void lruCacheTest(){
|
||||
Cache<String, String> lruCache = CacheUtil.newLRUCache(3);
|
||||
@ -71,7 +71,7 @@ public class CacheTest {
|
||||
String value2 = lruCache.get("key2");
|
||||
Assert.assertNull(value2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void timedCacheTest(){
|
||||
TimedCache<String, String> timedCache = CacheUtil.newTimedCache(4);
|
||||
@ -80,29 +80,29 @@ public class CacheTest {
|
||||
timedCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 5);//5秒过期
|
||||
timedCache.put("key3", "value3");//默认过期(4毫秒)
|
||||
timedCache.put("key4", "value4", Long.MAX_VALUE);//永不过期
|
||||
|
||||
|
||||
//启动定时任务,每5毫秒秒检查一次过期
|
||||
timedCache.schedulePrune(5);
|
||||
//等待5毫秒
|
||||
ThreadUtil.sleep(5);
|
||||
|
||||
|
||||
//5毫秒后由于value2设置了5毫秒过期,因此只有value2被保留下来
|
||||
String value1 = timedCache.get("key1");
|
||||
Assert.assertNull(value1);
|
||||
String value2 = timedCache.get("key2");
|
||||
Assert.assertEquals("value2", value2);
|
||||
|
||||
|
||||
//5毫秒后,由于设置了默认过期,key3只被保留4毫秒,因此为null
|
||||
String value3 = timedCache.get("key3");
|
||||
Assert.assertNull(value3);
|
||||
|
||||
|
||||
String value3Supplier = timedCache.get("key3", () -> "Default supplier");
|
||||
Assert.assertEquals("Default supplier", value3Supplier);
|
||||
|
||||
|
||||
// 永不过期
|
||||
String value4 = timedCache.get("key4");
|
||||
Assert.assertEquals("value4", value4);
|
||||
|
||||
|
||||
//取消定时清理
|
||||
timedCache.cancelPruneSchedule();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.5.9-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-captcha</artifactId>
|
||||
|
@ -13,7 +13,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* 圆圈干扰验证码
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 3.2.3
|
||||
*
|
||||
@ -23,7 +23,7 @@ public class CircleCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
*/
|
||||
@ -33,7 +33,7 @@ public class CircleCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
* @param codeCount 字符个数
|
||||
@ -44,7 +44,7 @@ public class CircleCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
* @param codeCount 字符个数
|
||||
@ -71,7 +71,7 @@ public class CircleCaptcha extends AbstractCaptcha {
|
||||
// ----------------------------------------------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 绘制字符串
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics2D}画笔
|
||||
* @param code 验证码
|
||||
*/
|
||||
@ -85,7 +85,7 @@ public class CircleCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 画随机干扰
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics2D}
|
||||
*/
|
||||
private void drawInterfere(Graphics2D g) {
|
||||
|
@ -5,7 +5,7 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 验证码接口,提供验证码对象接口定义
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
@ -18,14 +18,14 @@ public interface ICaptcha extends Serializable{
|
||||
|
||||
/**
|
||||
* 获取验证码的文字内容
|
||||
*
|
||||
*
|
||||
* @return 验证码文字内容
|
||||
*/
|
||||
String getCode();
|
||||
|
||||
/**
|
||||
* 验证验证码是否正确,建议忽略大小写
|
||||
*
|
||||
*
|
||||
* @param userInputCode 用户输入的验证码
|
||||
* @return 是否与生成的一直
|
||||
*/
|
||||
@ -33,7 +33,7 @@ public interface ICaptcha extends Serializable{
|
||||
|
||||
/**
|
||||
* 将验证码写出到目标流中
|
||||
*
|
||||
*
|
||||
* @param out 目标流
|
||||
*/
|
||||
void write(OutputStream out);
|
||||
|
@ -14,7 +14,7 @@ import cn.hutool.core.util.RandomUtil;
|
||||
|
||||
/**
|
||||
* 使用干扰线方式生成的图形验证码
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 3.1.2
|
||||
*/
|
||||
@ -24,7 +24,7 @@ public class LineCaptcha extends AbstractCaptcha {
|
||||
// -------------------------------------------------------------------- Constructor start
|
||||
/**
|
||||
* 构造,默认5位验证码,150条干扰线
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
*/
|
||||
@ -34,7 +34,7 @@ public class LineCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
* @param codeCount 字符个数
|
||||
@ -63,7 +63,7 @@ public class LineCaptcha extends AbstractCaptcha {
|
||||
// ----------------------------------------------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 绘制字符串
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics}画笔
|
||||
* @param code 验证码
|
||||
*/
|
||||
@ -77,7 +77,7 @@ public class LineCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 绘制干扰线
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics2D}画笔
|
||||
*/
|
||||
private void drawInterfere(Graphics2D g) {
|
||||
|
@ -13,7 +13,7 @@ import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* 扭曲干扰验证码
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 3.2.3
|
||||
*
|
||||
@ -23,7 +23,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
*/
|
||||
@ -33,7 +33,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
* @param codeCount 字符个数
|
||||
@ -44,7 +44,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param width 图片宽
|
||||
* @param height 图片高
|
||||
* @param codeCount 字符个数
|
||||
@ -73,7 +73,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
// ----------------------------------------------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 绘制字符串
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics}画笔
|
||||
* @param code 验证码
|
||||
*/
|
||||
@ -87,7 +87,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 扭曲
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics}
|
||||
* @param w1 w1
|
||||
* @param h1 h1
|
||||
@ -100,7 +100,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* X坐标扭曲
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics}
|
||||
* @param w1 宽
|
||||
* @param h1 高
|
||||
@ -125,7 +125,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* Y坐标扭曲
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics}
|
||||
* @param w1 宽
|
||||
* @param h1 高
|
||||
@ -150,7 +150,7 @@ public class ShearCaptcha extends AbstractCaptcha {
|
||||
|
||||
/**
|
||||
* 干扰线
|
||||
*
|
||||
*
|
||||
* @param g {@link Graphics}
|
||||
* @param x1 x1
|
||||
* @param y1 y1
|
||||
|
@ -5,21 +5,21 @@ import cn.hutool.core.util.RandomUtil;
|
||||
/**
|
||||
* 随机字符验证码生成器<br>
|
||||
* 可以通过传入的基础集合和长度随机生成验证码字符
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public abstract class AbstractGenerator implements CodeGenerator {
|
||||
private static final long serialVersionUID = 8685744597154953479L;
|
||||
|
||||
|
||||
/** 基础字符集合,用于随机获取字符串的字符集合 */
|
||||
protected final String baseStr;
|
||||
/** 验证码长度 */
|
||||
protected final int length;
|
||||
|
||||
|
||||
/**
|
||||
* 构造,使用字母+数字做为基础
|
||||
*
|
||||
*
|
||||
* @param count 生成验证码长度
|
||||
*/
|
||||
public AbstractGenerator(int count) {
|
||||
@ -28,7 +28,7 @@ public abstract class AbstractGenerator implements CodeGenerator {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param baseStr 基础字符集合,用于随机获取字符串的字符集合
|
||||
* @param length 生成验证码长度
|
||||
*/
|
||||
@ -39,7 +39,7 @@ public abstract class AbstractGenerator implements CodeGenerator {
|
||||
|
||||
/**
|
||||
* 获取长度验证码
|
||||
*
|
||||
*
|
||||
* @return 验证码长度
|
||||
*/
|
||||
public int getLength() {
|
||||
|
@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 验证码文字生成器
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.2
|
||||
*/
|
||||
@ -12,7 +12,7 @@ public interface CodeGenerator extends Serializable{
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
*
|
||||
*
|
||||
* @return 验证码
|
||||
*/
|
||||
String generate();
|
||||
@ -20,7 +20,7 @@ public interface CodeGenerator extends Serializable{
|
||||
/**
|
||||
* 验证用户输入的字符串是否与生成的验证码匹配<br>
|
||||
* 用户通过实现此方法定义验证码匹配方式
|
||||
*
|
||||
*
|
||||
* @param code 生成的随机验证码
|
||||
* @param userInputCode 用户输入的验证码
|
||||
* @return 是否验证通过
|
||||
|
@ -7,7 +7,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 数字计算验证码生成器
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.2
|
||||
*/
|
||||
@ -28,7 +28,7 @@ public class MathGenerator implements CodeGenerator {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param numberLength 参与计算最大数字位数
|
||||
*/
|
||||
public MathGenerator(int numberLength) {
|
||||
@ -75,7 +75,7 @@ public class MathGenerator implements CodeGenerator {
|
||||
|
||||
/**
|
||||
* 根据长度获取参与计算数字最大值
|
||||
*
|
||||
*
|
||||
* @return 最大值
|
||||
*/
|
||||
private int getLimit() {
|
||||
|
@ -6,7 +6,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
/**
|
||||
* 随机字符验证码生成器<br>
|
||||
* 可以通过传入的基础集合和长度随机生成验证码字符
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.2
|
||||
*/
|
||||
@ -15,7 +15,7 @@ public class RandomGenerator extends AbstractGenerator {
|
||||
|
||||
/**
|
||||
* 构造,使用字母+数字做为基础
|
||||
*
|
||||
*
|
||||
* @param count 生成验证码长度
|
||||
*/
|
||||
public RandomGenerator(int count) {
|
||||
@ -24,7 +24,7 @@ public class RandomGenerator extends AbstractGenerator {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param baseStr 基础字符集合,用于随机获取字符串的字符集合
|
||||
* @param length 生成验证码长度
|
||||
*/
|
||||
@ -36,7 +36,7 @@ public class RandomGenerator extends AbstractGenerator {
|
||||
public String generate() {
|
||||
return RandomUtil.randomString(this.baseStr, this.length);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean verify(String code, String userInputCode) {
|
||||
if (StrUtil.isNotBlank(userInputCode)) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 验证码生成策略实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.2
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 图片验证码实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -4,7 +4,7 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CaptchaUtilTest {
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void createTest() {
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.5.9-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-core</artifactId>
|
||||
|
@ -43,7 +43,7 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param element 需要解析注解的元素:可以是Class、Method、Field、Constructor、ReflectPermission
|
||||
*/
|
||||
public CombinationAnnotationElement(AnnotatedElement element) {
|
||||
@ -73,17 +73,17 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
||||
final Collection<Annotation> annotations = this.declaredAnnotationMap.values();
|
||||
return annotations.toArray(new Annotation[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
*
|
||||
* @param element 元素
|
||||
*/
|
||||
private void init(AnnotatedElement element) {
|
||||
final Annotation[] declaredAnnotations = element.getDeclaredAnnotations();
|
||||
this.declaredAnnotationMap = new HashMap<>();
|
||||
parseDeclared(declaredAnnotations);
|
||||
|
||||
|
||||
final Annotation[] annotations = element.getAnnotations();
|
||||
if(Arrays.equals(declaredAnnotations, annotations)) {
|
||||
this.annotationMap = this.declaredAnnotationMap;
|
||||
@ -109,7 +109,7 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 进行递归解析注解,直到全部都是元注解为止
|
||||
*
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 注解包,提供增强型注解和注解工具类
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -11,9 +11,9 @@ import cn.hutool.core.lang.func.Func0;
|
||||
*/
|
||||
public enum BeanDescCache {
|
||||
INSTANCE;
|
||||
|
||||
|
||||
private final SimpleCache<Class<?>, BeanDesc> bdCache = new SimpleCache<>();
|
||||
|
||||
|
||||
/**
|
||||
* 获得属性名和{@link BeanDesc}Map映射
|
||||
* @param beanClass Bean的类
|
||||
|
@ -13,19 +13,19 @@ public class BeanException extends RuntimeException{
|
||||
public BeanException(Throwable e) {
|
||||
super(ExceptionUtil.getMessage(e), e);
|
||||
}
|
||||
|
||||
|
||||
public BeanException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public BeanException(String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
}
|
||||
|
||||
|
||||
public BeanException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
|
||||
public BeanException(Throwable throwable, String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ import java.util.Map;
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* 表达式栗子:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
@ -33,7 +33,7 @@ import java.util.Map;
|
||||
* person.friends[5].name
|
||||
* ['person']['friends'][5]['name']
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @since 4.0.6
|
||||
*/
|
||||
@ -54,9 +54,9 @@ public class BeanPath implements Serializable{
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* 表达式栗子:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
@ -64,7 +64,7 @@ public class BeanPath implements Serializable{
|
||||
* person.friends[5].name
|
||||
* ['person']['friends'][5]['name']
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
* @return BeanPath
|
||||
*/
|
||||
@ -74,7 +74,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
*/
|
||||
public BeanPath(String expression) {
|
||||
@ -83,7 +83,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Bean中对应表达式的值
|
||||
*
|
||||
*
|
||||
* @param bean Bean对象或Map或List等
|
||||
* @return 值,如果对应值不存在,则返回null
|
||||
*/
|
||||
@ -95,29 +95,29 @@ public class BeanPath implements Serializable{
|
||||
* 设置表达式指定位置(或filed对应)的值<br>
|
||||
* 若表达式指向一个List则设置其坐标对应位置的值,若指向Map则put对应key的值,Bean则设置字段的值<br>
|
||||
* 注意:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1. 如果为List,如果下标不大于List长度,则替换原有值,否则追加值
|
||||
* 2. 如果为数组,如果下标不大于数组长度,则替换原有值,否则追加值
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param bean Bean、Map或List
|
||||
* @param value 值
|
||||
*/
|
||||
public void set(Object bean, Object value) {
|
||||
set(bean, this.patternParts, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置表达式指定位置(或filed对应)的值<br>
|
||||
* 若表达式指向一个List则设置其坐标对应位置的值,若指向Map则put对应key的值,Bean则设置字段的值<br>
|
||||
* 注意:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1. 如果为List,如果下标不大于List长度,则替换原有值,否则追加值
|
||||
* 2. 如果为数组,如果下标不大于数组长度,则替换原有值,否则追加值
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param bean Bean、Map或List
|
||||
* @param patternParts 表达式块列表
|
||||
* @param value 值
|
||||
@ -135,7 +135,7 @@ public class BeanPath implements Serializable{
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 获取Bean中对应表达式的值
|
||||
*
|
||||
*
|
||||
* @param patternParts 表达式分段列表
|
||||
* @param bean Bean对象或Map或List等
|
||||
* @param ignoreLast 是否忽略最后一个值,忽略最后一个值则用于set,否则用于read
|
||||
@ -215,7 +215,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
*/
|
||||
private void init(String expression) {
|
||||
@ -277,7 +277,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 对于非表达式去除单引号
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
* @return 表达式
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@ import java.util.Map;
|
||||
* 3. Map 转 Bean
|
||||
* 4. Map 转 Map
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
* @param <T> 目标对象类型
|
||||
@ -33,7 +33,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/** 源对象 */
|
||||
private final Object source;
|
||||
/** 目标对象 */
|
||||
@ -45,7 +45,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 创建BeanCopier
|
||||
*
|
||||
*
|
||||
* @param <T> 目标Bean类型
|
||||
* @param source 来源对象,可以是Bean或者Map
|
||||
* @param dest 目标Bean对象
|
||||
@ -58,7 +58,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 创建BeanCopier
|
||||
*
|
||||
*
|
||||
* @param <T> 目标Bean类型
|
||||
* @param source 来源对象,可以是Bean或者Map
|
||||
* @param dest 目标Bean对象
|
||||
@ -72,7 +72,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param source 来源对象,可以是Bean或者Map
|
||||
* @param dest 目标Bean对象
|
||||
* @param destType 目标的泛型类型,用于标注有泛型参数的Bean对象
|
||||
@ -115,7 +115,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* Bean和Bean之间属性拷贝
|
||||
*
|
||||
*
|
||||
* @param providerBean 来源Bean
|
||||
* @param destBean 目标Bean
|
||||
*/
|
||||
@ -125,7 +125,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* Map转Bean属性拷贝
|
||||
*
|
||||
*
|
||||
* @param map Map
|
||||
* @param bean Bean
|
||||
*/
|
||||
@ -138,7 +138,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* Map转Map
|
||||
*
|
||||
*
|
||||
* @param source 源Map
|
||||
* @param dest 目标Map
|
||||
*/
|
||||
@ -151,7 +151,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 对象转Map
|
||||
*
|
||||
*
|
||||
* @param bean bean对象
|
||||
* @param targetMap 目标的Map
|
||||
* @since 4.1.22
|
||||
@ -201,7 +201,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
/**
|
||||
* 值提供器转Bean<br>
|
||||
* 此方法通过遍历目标Bean的字段,从ValueProvider查找对应值
|
||||
*
|
||||
*
|
||||
* @param valueProvider 值提供器
|
||||
* @param bean Bean
|
||||
*/
|
||||
|
@ -6,17 +6,17 @@ import java.lang.reflect.Type;
|
||||
* 值提供者,用于提供Bean注入时参数对应值得抽象接口<br>
|
||||
* 继承或匿名实例化此接口<br>
|
||||
* 在Bean注入过程中,Bean获得字段名,通过外部方式根据这个字段名查找相应的字段值,然后注入Bean<br>
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @param <T> KEY类型,一般情况下为 {@link String}
|
||||
*
|
||||
*/
|
||||
public interface ValueProvider<T>{
|
||||
|
||||
|
||||
/**
|
||||
* 获取值<br>
|
||||
* 返回值一般需要匹配被注入类型,如果不匹配会调用默认转换 Convert#convert(Type, Object)实现转换
|
||||
*
|
||||
*
|
||||
* @param key Bean对象中参数名
|
||||
* @param valueType 被注入的值的类型
|
||||
* @return 对应参数名的值
|
||||
@ -26,7 +26,7 @@ public interface ValueProvider<T>{
|
||||
/**
|
||||
* 是否包含指定KEY,如果不包含则忽略注入<br>
|
||||
* 此接口方法单独需要实现的意义在于:有些值提供者(比如Map)key是存在的,但是value为null,此时如果需要注入这个null,需要根据此方法判断
|
||||
*
|
||||
*
|
||||
* @param key Bean对象中参数名
|
||||
* @return 是否包含指定KEY
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Bean拷贝实现,包括拷贝选项等
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Bean值提供者方式封装
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Bean相关操作,包括Bean信息描述,Bean路径表达式、动态Bean、Bean工具等
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 建造者模式接口定义
|
||||
*
|
||||
*
|
||||
* @param <T> 建造对象类型
|
||||
* @author Looly
|
||||
* @since 4.2.2
|
||||
@ -12,7 +12,7 @@ import java.io.Serializable;
|
||||
public interface Builder<T> extends Serializable{
|
||||
/**
|
||||
* 构建
|
||||
*
|
||||
*
|
||||
* @return 被构建的对象
|
||||
*/
|
||||
T build();
|
||||
|
@ -8,7 +8,7 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
/**
|
||||
* 用于构建 {@link java.lang.Comparable#compareTo(Object)} 方法的辅助工具
|
||||
*
|
||||
* <p>
|
||||
@ -33,7 +33,7 @@ import java.util.Comparator;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* 字段值按照顺序比较,如果某个字段返回非0结果,比较终止,使用{@code toComparison()}返回结果,后续比较忽略。
|
||||
*
|
||||
* <p>
|
||||
@ -52,7 +52,7 @@ import java.util.Comparator;
|
||||
*/
|
||||
public class CompareToBuilder implements Builder<Integer> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/** 当前比较状态 */
|
||||
private int comparison;
|
||||
|
||||
@ -60,12 +60,11 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* 构造,构造后调用append方法增加比较项,然后调用{@link #toComparison()}获取结果
|
||||
*/
|
||||
public CompareToBuilder() {
|
||||
super();
|
||||
comparison = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
/**
|
||||
* 通过反射比较两个Bean对象,对象字段可以为private。比较规则如下:
|
||||
*
|
||||
* <ul>
|
||||
@ -94,7 +93,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@ -126,7 +125,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@ -159,7 +158,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@ -192,7 +191,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@ -221,10 +220,10 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* @since 2.2 (2.0 as <code>reflectionCompare(Object, Object, boolean, Class)</code>)
|
||||
*/
|
||||
public static int reflectionCompare(
|
||||
final Object lhs,
|
||||
final Object rhs,
|
||||
final boolean compareTransients,
|
||||
final Class<?> reflectUpToClass,
|
||||
final Object lhs,
|
||||
final Object rhs,
|
||||
final boolean compareTransients,
|
||||
final Class<?> reflectUpToClass,
|
||||
final String... excludeFields) {
|
||||
|
||||
if (lhs == rhs) {
|
||||
@ -249,7 +248,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
/**
|
||||
* <p>Appends to <code>builder</code> the comparison of <code>lhs</code>
|
||||
* to <code>rhs</code> using the fields defined in <code>clazz</code>.</p>
|
||||
*
|
||||
*
|
||||
* @param lhs left-hand object
|
||||
* @param rhs right-hand object
|
||||
* @param clazz <code>Class</code> that defines fields to be compared
|
||||
@ -264,7 +263,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
final CompareToBuilder builder,
|
||||
final boolean useTransients,
|
||||
final String[] excludeFields) {
|
||||
|
||||
|
||||
final Field[] fields = clazz.getDeclaredFields();
|
||||
AccessibleObject.setAccessible(fields, true);
|
||||
for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
|
||||
@ -300,7 +299,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
comparison = superCompareTo;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Appends to the <code>builder</code> the comparison of
|
||||
@ -312,7 +311,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* a <code>null</code> object is less than a non-<code>null</code> object</li>
|
||||
* <li>Check the object contents</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* <p><code>lhs</code> must either be an array or implement {@link Comparable}.</p>
|
||||
*
|
||||
* @param lhs left-hand object
|
||||
@ -441,7 +440,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
/**
|
||||
* Appends to the <code>builder</code> the comparison of
|
||||
* two <code>short</code>s.
|
||||
*
|
||||
*
|
||||
* @param lhs left-hand value
|
||||
* @param rhs right-hand value
|
||||
* @return this - used to chain append calls
|
||||
@ -473,7 +472,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
/**
|
||||
* Appends to the <code>builder</code> the comparison of
|
||||
* two <code>byte</code>s.
|
||||
*
|
||||
*
|
||||
* @param lhs left-hand value
|
||||
* @param rhs right-hand value
|
||||
* @return this - used to chain append calls
|
||||
@ -575,7 +574,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
public CompareToBuilder append(final Object[] lhs, final Object[] rhs) {
|
||||
return append(lhs, rhs, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Appends to the <code>builder</code> the deep comparison of
|
||||
* two <code>Object</code> arrays.</p>
|
||||
@ -950,7 +949,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* the <code>builder</code> has judged the "left-hand" side
|
||||
* as less than, greater than, or equal to the "right-hand"
|
||||
* side.
|
||||
*
|
||||
*
|
||||
* @return final comparison result
|
||||
* @see #build()
|
||||
*/
|
||||
@ -963,7 +962,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* the <code>builder</code> has judged the "left-hand" side
|
||||
* as less than, greater than, or equal to the "right-hand"
|
||||
* side.
|
||||
*
|
||||
*
|
||||
* @return final comparison result as an Integer
|
||||
* @see #toComparison()
|
||||
* @since 3.0
|
||||
|
@ -85,17 +85,17 @@ import cn.hutool.core.util.ArrayUtil;
|
||||
*/
|
||||
public class HashCodeBuilder implements Builder<Integer> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* The default initial value to use in reflection hash code building.
|
||||
*/
|
||||
private static final int DEFAULT_INITIAL_VALUE = 17;
|
||||
|
||||
|
||||
/**
|
||||
* The default multipler value to use in reflection hash code building.
|
||||
*/
|
||||
private static final int DEFAULT_MULTIPLIER_VALUE = 37;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
|
||||
@ -103,7 +103,7 @@ public class HashCodeBuilder implements Builder<Integer> {
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<Set<IDKey>>();
|
||||
private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<>();
|
||||
|
||||
/*
|
||||
* NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
|
||||
@ -380,7 +380,7 @@ public class HashCodeBuilder implements Builder<Integer> {
|
||||
* if the object is <code>null</code>
|
||||
*/
|
||||
public static int reflectionHashCode(final Object object, final boolean testTransients) {
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
|
||||
testTransients, null);
|
||||
}
|
||||
|
||||
@ -457,7 +457,7 @@ public class HashCodeBuilder implements Builder<Integer> {
|
||||
* if the object is <code>null</code>
|
||||
*/
|
||||
public static int reflectionHashCode(final Object object, final String... excludeFields) {
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
|
||||
null, excludeFields);
|
||||
}
|
||||
|
||||
|
@ -13,13 +13,13 @@ import java.io.Serializable;
|
||||
*/
|
||||
final class IDKey implements Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final Object value;
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param obj 计算唯一ID的对象
|
||||
*/
|
||||
public IDKey(final Object obj) {
|
||||
@ -32,7 +32,7 @@ final class IDKey implements Serializable{
|
||||
|
||||
/**
|
||||
* returns hashcode - i.e. the system identity hashcode.
|
||||
*
|
||||
*
|
||||
* @return the hashcode
|
||||
*/
|
||||
@Override
|
||||
@ -42,7 +42,7 @@ final class IDKey implements Serializable{
|
||||
|
||||
/**
|
||||
* checks if instances are equal
|
||||
*
|
||||
*
|
||||
* @param other The other object to compare to
|
||||
* @return if the instances are for the same object
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 建造者工具<br>
|
||||
* 用于建造特定对象或结果
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -13,19 +13,19 @@ public class CloneRuntimeException extends RuntimeException{
|
||||
public CloneRuntimeException(Throwable e) {
|
||||
super(ExceptionUtil.getMessage(e), e);
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(Throwable throwable, String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package cn.hutool.core.clone;
|
||||
* @param <T> 继承类的类型
|
||||
*/
|
||||
public class CloneSupport<T> implements Cloneable<T>{
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T clone() {
|
||||
@ -17,5 +17,5 @@ public class CloneSupport<T> implements Cloneable<T>{
|
||||
throw new CloneRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package cn.hutool.core.clone;
|
||||
* @param <T> 实现克隆接口的类型
|
||||
*/
|
||||
public interface Cloneable<T> extends java.lang.Cloneable{
|
||||
|
||||
|
||||
/**
|
||||
* 克隆当前对象,浅复制
|
||||
* @return 克隆后的对象
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 克隆封装
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@ import cn.hutool.core.lang.Assert;
|
||||
*
|
||||
*/
|
||||
public class BCD {
|
||||
|
||||
|
||||
/**
|
||||
* 字符串转BCD码
|
||||
* @param asc ASCII字符串
|
||||
@ -53,7 +53,7 @@ public class BCD {
|
||||
}
|
||||
return bbt;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ASCII转BCD
|
||||
* @param ascii ASCII byte数组
|
||||
@ -100,8 +100,8 @@ public class BCD {
|
||||
}
|
||||
return new String(temp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 转换单个byte为BCD
|
||||
|
@ -14,7 +14,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
*
|
||||
*/
|
||||
public class Base32 {
|
||||
|
||||
|
||||
private Base32() {}
|
||||
|
||||
private static final String BASE32_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
@ -73,10 +73,10 @@ public class Base32 {
|
||||
|
||||
return base32.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base32编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base32字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -86,7 +86,7 @@ public class Base32 {
|
||||
|
||||
/**
|
||||
* base32编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -97,7 +97,7 @@ public class Base32 {
|
||||
|
||||
/**
|
||||
* base32编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -155,10 +155,10 @@ public class Base32 {
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base32解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base32字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -168,7 +168,7 @@ public class Base32 {
|
||||
|
||||
/**
|
||||
* base32解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -176,10 +176,10 @@ public class Base32 {
|
||||
public static String decodeStr(String source, String charset) {
|
||||
return StrUtil.str(decode(source), charset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base32解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
|
@ -12,7 +12,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* Base62工具类,提供Base62的编码和解码方案<br>
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @since 4.5.9
|
||||
*/
|
||||
@ -24,7 +24,7 @@ public class Base62 {
|
||||
// -------------------------------------------------------------------- encode
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -34,7 +34,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的Base62字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -45,7 +45,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -55,7 +55,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param in 被编码Base62的流(一般为图片流或者文件流)
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -65,7 +65,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param file 被编码Base62的文件
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -76,7 +76,7 @@ public class Base62 {
|
||||
// -------------------------------------------------------------------- decode
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -86,7 +86,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -96,7 +96,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的Base62字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -107,7 +107,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param Base62 被解码的Base62字符串
|
||||
* @param destFile 目标文件
|
||||
* @return 目标文件
|
||||
@ -118,7 +118,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param base62Str 被解码的Base62字符串
|
||||
* @param out 写出到的流
|
||||
* @param isCloseOut 是否关闭输出流
|
||||
@ -129,7 +129,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param base62Str 被解码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -139,7 +139,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* 解码Base62
|
||||
*
|
||||
*
|
||||
* @param base62bytes Base62输入
|
||||
* @return 解码后的bytes
|
||||
*/
|
||||
|
@ -48,16 +48,16 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 创建GMP风格的Base62编码解码器对象
|
||||
*
|
||||
*
|
||||
* @return Base62Codec
|
||||
*/
|
||||
public static Base62Codec createGmp() {
|
||||
return new Base62Codec(GMP);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建Inverted风格的Base62编码解码器对象
|
||||
*
|
||||
*
|
||||
* @return Base62Codec
|
||||
*/
|
||||
public static Base62Codec createInverted() {
|
||||
@ -69,7 +69,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param alphabet 自定义字母表
|
||||
*/
|
||||
public Base62Codec(byte[] alphabet) {
|
||||
@ -93,7 +93,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 解码Base62消息
|
||||
*
|
||||
*
|
||||
* @param encoded Base62内容
|
||||
* @return 消息
|
||||
*/
|
||||
@ -105,7 +105,7 @@ public class Base62Codec implements Serializable{
|
||||
// --------------------------------------------------------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 按照字典转换bytes
|
||||
*
|
||||
*
|
||||
* @param indices 内容
|
||||
* @param dictionary 字典
|
||||
* @return 转换值
|
||||
@ -122,7 +122,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 使用定义的字母表从源基准到目标基准
|
||||
*
|
||||
*
|
||||
* @param message 消息bytes
|
||||
* @param sourceBase 源基准长度
|
||||
* @param targetBase 目标基准长度
|
||||
@ -167,7 +167,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 估算结果长度
|
||||
*
|
||||
*
|
||||
* @param inputLength 输入长度
|
||||
* @param sourceBase 源基准长度
|
||||
* @param targetBase 目标基准长度
|
||||
|
@ -8,7 +8,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* Base64解码实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
@ -41,7 +41,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -51,7 +51,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base64字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -62,7 +62,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -72,7 +72,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* 解码Base64
|
||||
*
|
||||
*
|
||||
* @param in 输入
|
||||
* @return 解码后的bytes
|
||||
*/
|
||||
@ -85,7 +85,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* 解码Base64
|
||||
*
|
||||
*
|
||||
* @param in 输入
|
||||
* @param pos 开始位置
|
||||
* @param length 长度
|
||||
@ -133,7 +133,7 @@ public class Base64Decoder {
|
||||
// ----------------------------------------------------------------------------------------------- Private start
|
||||
/**
|
||||
* 获取下一个有效的byte字符
|
||||
*
|
||||
*
|
||||
* @param in 输入
|
||||
* @param pos 当前位置,调用此方法后此位置保持在有效字符的下一个位置
|
||||
* @param maxPos 最大位置
|
||||
@ -157,7 +157,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* int包装,使之可变
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@ import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Base64编码
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 3.2.0
|
||||
*/
|
||||
@ -40,7 +40,7 @@ public class Base64Encoder {
|
||||
// -------------------------------------------------------------------- encode
|
||||
/**
|
||||
* 编码为Base64,非URL安全的
|
||||
*
|
||||
*
|
||||
* @param arr 被编码的数组
|
||||
* @param lineSep 在76个char之后是CRLF还是EOF
|
||||
* @return 编码后的bytes
|
||||
@ -51,7 +51,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* 编码为Base64,URL安全的
|
||||
*
|
||||
*
|
||||
* @param arr 被编码的数组
|
||||
* @param lineSep 在76个char之后是CRLF还是EOF
|
||||
* @return 编码后的bytes
|
||||
@ -63,7 +63,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -73,7 +73,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码,URL安全
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
* @since 3.0.6
|
||||
@ -84,7 +84,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -95,7 +95,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码,URL安全的
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@ -107,7 +107,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@ -117,7 +117,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码,URL安全的
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
* @since 3.0.6
|
||||
@ -129,7 +129,7 @@ public class Base64Encoder {
|
||||
/**
|
||||
* 编码为Base64<br>
|
||||
* 如果isMultiLine为{@code true},则每76个字符一个换行符,否则在一行显示
|
||||
*
|
||||
*
|
||||
* @param arr 被编码的数组
|
||||
* @param isMultiLine 在76个char之后是CRLF还是EOF
|
||||
* @param isUrlSafe 是否使用URL安全字符,一般为{@code false}
|
||||
|
@ -11,7 +11,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
/**
|
||||
* 莫尔斯电码的编码和解码实现<br>
|
||||
* 参考:https://github.com/TakWolf/Java-MorseCoder
|
||||
*
|
||||
*
|
||||
* @author looly, TakWolf
|
||||
* @since 4.4.1
|
||||
*/
|
||||
@ -22,7 +22,7 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 注册莫尔斯电码表
|
||||
*
|
||||
*
|
||||
* @param abc 字母和字符
|
||||
* @param dict 二进制
|
||||
*/
|
||||
@ -104,7 +104,7 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param dit 点表示的字符
|
||||
* @param dah 横线表示的字符
|
||||
* @param split 分隔符
|
||||
@ -117,13 +117,13 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*
|
||||
*
|
||||
* @param text 文本
|
||||
* @return 密文
|
||||
*/
|
||||
public String encode(String text) {
|
||||
Assert.notNull(text, "Text should not be null.");
|
||||
|
||||
|
||||
text = text.toUpperCase();
|
||||
final StringBuilder morseBuilder = new StringBuilder();
|
||||
final int len = text.codePointCount(0, text.length());
|
||||
@ -140,7 +140,7 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 解码
|
||||
*
|
||||
*
|
||||
* @param morse 莫尔斯电码
|
||||
* @return 明文
|
||||
*/
|
||||
|
@ -3,7 +3,7 @@ package cn.hutool.core.codec;
|
||||
/**
|
||||
* RotN(rotate by N places),回转N位密码,是一种简易的替换式密码,也是过去在古罗马开发的凯撒加密的一种变体。<br>
|
||||
* 代码来自:https://github.com/orclight/jencrypt
|
||||
*
|
||||
*
|
||||
* @author looly,shuzhilong
|
||||
* @since 4.4.1
|
||||
*/
|
||||
@ -18,7 +18,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13编码,同时编码数字
|
||||
*
|
||||
*
|
||||
* @param message 被编码的消息
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
@ -28,7 +28,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13编码
|
||||
*
|
||||
*
|
||||
* @param message 被编码的消息
|
||||
* @param isEnocdeNumber 是否编码数字
|
||||
* @return 编码后的字符串
|
||||
@ -39,7 +39,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* RotN编码
|
||||
*
|
||||
*
|
||||
* @param message 被编码的消息
|
||||
* @param offset 位移,常用位移13
|
||||
* @param isEnocdeNumber 是否编码数字
|
||||
@ -57,7 +57,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13解码,同时解码数字
|
||||
*
|
||||
*
|
||||
* @param rot 被解码的消息密文
|
||||
* @return 解码后的字符串
|
||||
*/
|
||||
@ -67,7 +67,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13解码
|
||||
*
|
||||
*
|
||||
* @param rot 被解码的消息密文
|
||||
* @param isDecodeNumber 是否解码数字
|
||||
* @return 解码后的字符串
|
||||
@ -78,7 +78,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* RotN解码
|
||||
*
|
||||
*
|
||||
* @param rot 被解码的消息密文
|
||||
* @param offset 位移,常用位移13
|
||||
* @param isDecodeNumber 是否解码数字
|
||||
@ -97,7 +97,7 @@ public class Rot {
|
||||
// ------------------------------------------------------------------------------------------ Private method start
|
||||
/**
|
||||
* 解码字符
|
||||
*
|
||||
*
|
||||
* @param c 字符
|
||||
* @param offset 位移
|
||||
* @param isDecodeNumber 是否解码数字
|
||||
@ -129,7 +129,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* 编码字符
|
||||
*
|
||||
*
|
||||
* @param c 字符
|
||||
* @param offset 位移
|
||||
* @param isDecodeNumber 是否编码数字
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* BaseN以及BCD编码封装
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -58,7 +58,7 @@ public class ArrayIter<E> implements Iterator<E>, Iterable<E>, Serializable{
|
||||
if(endIndex > 0 && endIndex < this.endIndex){
|
||||
this.endIndex = endIndex;
|
||||
}
|
||||
|
||||
|
||||
if(startIndex >=0 && startIndex < this.endIndex){
|
||||
this.startIndex = startIndex;
|
||||
}
|
||||
|
@ -15,15 +15,15 @@ import java.util.PriorityQueue;
|
||||
*/
|
||||
public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
private static final long serialVersionUID = 3794348988671694820L;
|
||||
|
||||
|
||||
//容量
|
||||
private final int capacity;
|
||||
private final Comparator<? super E> comparator;
|
||||
|
||||
|
||||
public BoundedPriorityQueue(int capacity) {
|
||||
this(capacity, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param capacity 容量
|
||||
@ -63,7 +63,7 @@ public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
}
|
||||
return super.offer(e);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加多个元素<br>
|
||||
* 参数为集合的情况请使用{@link PriorityQueue#addAll}
|
||||
@ -73,7 +73,7 @@ public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
public boolean addAll(E[] c) {
|
||||
return this.addAll(Arrays.asList(c));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return 返回排序后的列表
|
||||
*/
|
||||
@ -82,7 +82,7 @@ public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
list.sort(comparator);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return toList().iterator();
|
||||
|
@ -2780,11 +2780,11 @@ public class CollUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 取最大值
|
||||
* 取最小值
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param coll 集合
|
||||
* @return 最大值
|
||||
* @return 最小值
|
||||
* @see Collections#min(Collection)
|
||||
* @since 4.6.5
|
||||
*/
|
||||
@ -2988,4 +2988,25 @@ public class CollUtil {
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个{@link Collection} 是否元素和顺序相同,返回{@code true}的条件是:
|
||||
* <ul>
|
||||
* <li>两个{@link Collection}必须长度相同</li>
|
||||
* <li>两个{@link Collection}元素相同index的对象必须equals,满足{@link Objects#equals(Object, Object)}</li>
|
||||
* </ul>
|
||||
* 此方法来自Apache-Commons-Collections4。
|
||||
*
|
||||
* @param list1 列表1
|
||||
* @param list2 列表2
|
||||
* @return 是否相同
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static boolean isEqualList(final Collection<?> list1, final Collection<?> list2) {
|
||||
if (list1 == null || list2 == null || list1.size() != list2.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IterUtil.isEqualList(list1, list2);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package cn.hutool.core.collection;
|
||||
|
||||
/**
|
||||
* 集合相关工具类,包括数组,是{@link CollUtil} 的别名工具类类
|
||||
*
|
||||
*
|
||||
* @author xiaoleilu
|
||||
* @see CollUtil
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 通过{@link ConcurrentHashMap}实现的线程安全HashSet
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
@ -32,7 +32,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
/**
|
||||
* 构造<br>
|
||||
* 触发因子为默认的0.75
|
||||
*
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
*/
|
||||
public ConcurrentHashSet(int initialCapacity) {
|
||||
@ -41,7 +41,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 加载因子。此参数决定数据增长时触发的百分比
|
||||
*/
|
||||
@ -51,7 +51,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 触发因子。此参数决定数据增长时触发的百分比
|
||||
* @param concurrencyLevel 线程并发度
|
||||
@ -59,7 +59,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
public ConcurrentHashSet(int initialCapacity, float loadFactor, int concurrencyLevel) {
|
||||
map = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从已有集合中构造
|
||||
* @param iter {@link Iterable}
|
||||
|
@ -8,14 +8,14 @@ import java.util.List;
|
||||
* 复制 {@link Iterator}<br>
|
||||
* 为了解决并发情况下{@link Iterator}遍历导致的问题(当Iterator被修改会抛出ConcurrentModificationException)
|
||||
* ,故使用复制原Iterator的方式解决此问题。
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 解决方法为:在构造方法中遍历Iterator中的元素,装入新的List中然后遍历之。
|
||||
* 当然,修改这个复制后的Iterator是没有意义的,因此remove方法将会抛出异常。
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 需要注意的是,在构造此对象时需要保证原子性(原对象不被修改),最好加锁构造此对象,构造完毕后解锁。
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
* @author Looly
|
||||
@ -25,7 +25,7 @@ public class CopiedIter<E> implements Iterator<E>, Iterable<E>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Iterator<E> listIterator;
|
||||
|
||||
|
||||
public static <V> CopiedIter<V> copyOf(Iterator<V> iterator){
|
||||
return new CopiedIter<>(iterator);
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ import java.util.Iterator;
|
||||
*/
|
||||
public class EnumerationIter<E> implements Iterator<E>, Iterable<E>, Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final Enumeration<E> e;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param enumeration {@link Enumeration}对象
|
||||
|
@ -18,6 +18,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@ -612,7 +613,7 @@ public class IterUtil {
|
||||
/**
|
||||
* Enumeration转换为Iterator
|
||||
* <p>
|
||||
* Adapt the specified <code>Enumeration</code> to the <code>Iterator</code> interface
|
||||
* Adapt the specified {@code Enumeration} to the {@code Iterator} interface
|
||||
*
|
||||
* @param <E> 集合元素类型
|
||||
* @param e {@link Enumeration}
|
||||
@ -859,4 +860,39 @@ public class IterUtil {
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个{@link Iterable} 是否元素和顺序相同,返回{@code true}的条件是:
|
||||
* <ul>
|
||||
* <li>两个{@link Iterable}必须长度相同</li>
|
||||
* <li>两个{@link Iterable}元素相同index的对象必须equals,满足{@link Objects#equals(Object, Object)}</li>
|
||||
* </ul>
|
||||
* 此方法来自Apache-Commons-Collections4。
|
||||
*
|
||||
* @param list1 列表1
|
||||
* @param list2 列表2
|
||||
* @return 是否相同
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static boolean isEqualList(final Iterable<?> list1, final Iterable<?> list2) {
|
||||
if (list1 == list2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Iterator<?> it1 = list1.iterator();
|
||||
final Iterator<?> it2 = list2.iterator();
|
||||
Object obj1;
|
||||
Object obj2;
|
||||
while (it1.hasNext() && it2.hasNext()) {
|
||||
obj1 = it1.next();
|
||||
obj2 = it2.next();
|
||||
|
||||
if (false == Objects.equals(obj1, obj2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 当两个Iterable长度不一致时返回false
|
||||
return false == (it1.hasNext() || it2.hasNext());
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ import java.util.Iterator;
|
||||
*/
|
||||
public class IteratorEnumeration<E> implements Enumeration<E>, Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final Iterator<E> iterator;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param iterator {@link Iterator}对象
|
||||
|
@ -17,7 +17,7 @@ import cn.hutool.core.lang.Assert;
|
||||
/**
|
||||
* 将Reader包装为一个按照行读取的Iterator<br>
|
||||
* 此对象遍历结束后,应关闭之,推荐使用方式:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* LineIterator it = null;
|
||||
* try {
|
||||
@ -30,7 +30,7 @@ import cn.hutool.core.lang.Assert;
|
||||
* it.close();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* 此类来自于Apache Commons io
|
||||
*
|
||||
* @author looly
|
||||
@ -45,7 +45,7 @@ public class LineIter implements Iterator<String>, Iterable<String>, Closeable,
|
||||
private String cachedLine;
|
||||
/** A flag indicating if the iterator has been fully read. */
|
||||
private boolean finished = false;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
@ -148,7 +148,7 @@ public class LineIter implements Iterator<String>, Iterable<String>, Closeable,
|
||||
|
||||
/**
|
||||
* 重写此方法来判断是否每一行都被返回,默认全部为true
|
||||
*
|
||||
*
|
||||
* @param line 需要验证的行
|
||||
* @return 是否通过验证
|
||||
*/
|
||||
|
@ -246,7 +246,7 @@ public class ListUtil {
|
||||
// 每页条目数大于总数直接返回所有
|
||||
if (resultSize <= pageSize) {
|
||||
if (pageNo < (PageUtil.getFirstPageNo() + 1)) {
|
||||
return Collections.unmodifiableList(list);
|
||||
return unmodifiable(list);
|
||||
} else {
|
||||
// 越界直接返回空
|
||||
return new ArrayList<>(0);
|
||||
@ -262,11 +262,11 @@ public class ListUtil {
|
||||
if (startEnd[1] > resultSize) {
|
||||
startEnd[1] = resultSize;
|
||||
if (startEnd[0] > startEnd[1]) {
|
||||
return empty();
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
}
|
||||
|
||||
return list.subList(startEnd[0], startEnd[1]);
|
||||
return sub(list, startEnd[0], startEnd[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,7 +366,8 @@ public class ListUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取集合的部分
|
||||
* 截取集合的部分<br>
|
||||
* 此方法与{@link List#subList(int, int)} 不同在于子列表是新的副本,操作子列表不会影响原列表。
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 被截取的数组
|
||||
@ -407,8 +408,8 @@ public class ListUtil {
|
||||
end = size;
|
||||
}
|
||||
|
||||
if (step <= 1) {
|
||||
return list.subList(start, end);
|
||||
if (step < 1) {
|
||||
step = 1;
|
||||
}
|
||||
|
||||
final List<T> result = new ArrayList<>();
|
||||
|
@ -21,7 +21,6 @@ public class ComparableComparator<E extends Comparable<? super E>> implements Co
|
||||
* 构造
|
||||
*/
|
||||
public ComparableComparator() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,9 +28,9 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 类型转换器
|
||||
*
|
||||
*
|
||||
* @author xiaoleilu
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class Convert {
|
||||
|
||||
@ -38,7 +38,7 @@ public class Convert {
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -51,17 +51,17 @@ public class Convert {
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static String toStr(Object value) {
|
||||
return toStr(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为String数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return String数组
|
||||
* @since 3.2.0
|
||||
@ -74,7 +74,7 @@ public class Convert {
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -87,17 +87,17 @@ public class Convert {
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Character toChar(Object value) {
|
||||
return toChar(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Character数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Character数组
|
||||
* @since 3.2.0
|
||||
@ -110,7 +110,7 @@ public class Convert {
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -123,17 +123,17 @@ public class Convert {
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Byte toByte(Object value) {
|
||||
return toByte(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Byte数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Byte数组
|
||||
* @since 3.2.0
|
||||
@ -157,7 +157,7 @@ public class Convert {
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -170,17 +170,17 @@ public class Convert {
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Short toShort(Object value) {
|
||||
return toShort(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Short数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Short数组
|
||||
* @since 3.2.0
|
||||
@ -193,7 +193,7 @@ public class Convert {
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -206,17 +206,17 @@ public class Convert {
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Number toNumber(Object value) {
|
||||
return toNumber(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Number数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Number数组
|
||||
* @since 3.2.0
|
||||
@ -229,7 +229,7 @@ public class Convert {
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -242,7 +242,7 @@ public class Convert {
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -264,7 +264,7 @@ public class Convert {
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -277,7 +277,7 @@ public class Convert {
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -287,7 +287,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -299,7 +299,7 @@ public class Convert {
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -312,7 +312,7 @@ public class Convert {
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -322,7 +322,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Double数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -334,7 +334,7 @@ public class Convert {
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -347,7 +347,7 @@ public class Convert {
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -357,7 +357,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Float数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -369,7 +369,7 @@ public class Convert {
|
||||
* 转换为boolean<br>
|
||||
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -382,7 +382,7 @@ public class Convert {
|
||||
* 转换为boolean<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -392,7 +392,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Boolean数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -404,7 +404,7 @@ public class Convert {
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -417,7 +417,7 @@ public class Convert {
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@ -429,7 +429,7 @@ public class Convert {
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -442,19 +442,19 @@ public class Convert {
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回null<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static BigDecimal toBigDecimal(Object value) {
|
||||
return toBigDecimal(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Date<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@ -489,7 +489,7 @@ public class Convert {
|
||||
public static LocalDateTime toLocalDateTime(Object value) {
|
||||
return toLocalDateTime(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instant<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
@ -508,7 +508,7 @@ public class Convert {
|
||||
* 转换为Date<br>
|
||||
* 如果给定的值为空,或者转换失败,返回{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
* @since 4.1.6
|
||||
@ -516,11 +516,11 @@ public class Convert {
|
||||
public static Date toDate(Object value) {
|
||||
return toDate(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
*
|
||||
*
|
||||
* @param <E> 枚举类型
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
@ -535,7 +535,7 @@ public class Convert {
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
*
|
||||
*
|
||||
* @param <E> 枚举类型
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
@ -547,7 +547,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为集合类
|
||||
*
|
||||
*
|
||||
* @param collectionType 集合类型
|
||||
* @param elementType 集合中元素类型
|
||||
* @param value 被转换的值
|
||||
@ -557,10 +557,10 @@ public class Convert {
|
||||
public static Collection<?> toCollection(Class<?> collectionType, Class<?> elementType, Object value) {
|
||||
return new CollectionConverter(collectionType, elementType).convert(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为ArrayList,元素类型默认Object
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return {@link List}
|
||||
* @since 4.1.11
|
||||
@ -568,10 +568,10 @@ public class Convert {
|
||||
public static List<?> toList(Object value) {
|
||||
return convert(List.class, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为ArrayList
|
||||
*
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param elementType 集合中元素类型
|
||||
* @param value 被转换的值
|
||||
@ -598,10 +598,10 @@ public class Convert {
|
||||
public static <K, V> Map<K, V> toMap(Class<K> keyType, Class<V> valueType, Object value) {
|
||||
return (Map<K, V>) new MapConverter(HashMap.class, keyType, valueType).convert(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型,类型采用字符串表示
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param className 类的字符串表示
|
||||
* @param value 值
|
||||
@ -612,10 +612,10 @@ public class Convert {
|
||||
public static <T> T convertByClassName(String className, Object value) throws ConvertException{
|
||||
return convert(ClassUtil.loadClass(className), value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@ -626,10 +626,10 @@ public class Convert {
|
||||
public static <T> T convert(Class<T> type, Object value) throws ConvertException{
|
||||
return convert((Type)type, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param reference 类型参考,用于持有转换后的泛型类型
|
||||
* @param value 值
|
||||
@ -642,7 +642,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@ -652,10 +652,10 @@ public class Convert {
|
||||
public static <T> T convert(Type type, Object value) throws ConvertException{
|
||||
return convert(type, value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@ -667,10 +667,10 @@ public class Convert {
|
||||
public static <T> T convert(Class<T> type, Object value, T defaultValue) throws ConvertException {
|
||||
return convert((Type)type, value, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@ -681,11 +681,11 @@ public class Convert {
|
||||
public static <T> T convert(Type type, Object value, T defaultValue) throws ConvertException {
|
||||
return convertWithCheck(type, value, defaultValue, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型,不抛异常转换<br>
|
||||
* 当转换失败时返回{@code null}
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 目标类型
|
||||
* @param value 值
|
||||
@ -695,11 +695,11 @@ public class Convert {
|
||||
public static <T> T convertQuietly(Type type, Object value) {
|
||||
return convertQuietly(type, value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型,不抛异常转换<br>
|
||||
* 当转换失败时返回默认值
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 目标类型
|
||||
* @param value 值
|
||||
@ -734,11 +734,11 @@ public class Convert {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------- 全角半角转换
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
*
|
||||
* @param input String.
|
||||
* @return 全角字符串.
|
||||
*/
|
||||
@ -748,7 +748,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
*
|
||||
* @param input String
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 全角字符串.
|
||||
@ -773,7 +773,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 全角转半角
|
||||
*
|
||||
*
|
||||
* @param input String.
|
||||
* @return 半角字符串
|
||||
*/
|
||||
@ -783,7 +783,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 替换全角为半角
|
||||
*
|
||||
*
|
||||
* @param text 文本
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 替换后的字符
|
||||
@ -813,7 +813,7 @@ public class Convert {
|
||||
// --------------------------------------------------------------------- hex
|
||||
/**
|
||||
* 字符串转换成十六进制字符串,结果为小写
|
||||
*
|
||||
*
|
||||
* @param str 待转换的ASCII字符串
|
||||
* @param charset 编码
|
||||
* @return 16进制字符串
|
||||
@ -825,7 +825,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte数组转16进制串
|
||||
*
|
||||
*
|
||||
* @param bytes 被转换的byte数组
|
||||
* @return 转换后的值
|
||||
* @see HexUtil#encodeHexStr(byte[])
|
||||
@ -836,7 +836,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* Hex字符串转换为Byte值
|
||||
*
|
||||
*
|
||||
* @param src Byte字符串,每个Byte之间没有分隔符
|
||||
* @return byte[]
|
||||
* @see HexUtil#decodeHex(char[])
|
||||
@ -847,7 +847,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 十六进制转换字符串
|
||||
*
|
||||
*
|
||||
* @param hexStr Byte字符串(Byte之间无分隔符 如:[616C6B])
|
||||
* @param charset 编码 {@link Charset}
|
||||
* @return 对应的字符串
|
||||
@ -858,10 +858,10 @@ public class Convert {
|
||||
public static String hexStrToStr(String hexStr, Charset charset) {
|
||||
return hexToStr(hexStr, charset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 十六进制转换字符串
|
||||
*
|
||||
*
|
||||
* @param hexStr Byte字符串(Byte之间无分隔符 如:[616C6B])
|
||||
* @param charset 编码 {@link Charset}
|
||||
* @return 对应的字符串
|
||||
@ -874,7 +874,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* String的字符串转换成unicode的String
|
||||
*
|
||||
*
|
||||
* @param strText 全角字符串
|
||||
* @return String 每个unicode之间无分隔符
|
||||
* @see UnicodeUtil#toUnicode(String)
|
||||
@ -885,7 +885,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* unicode的String转换成String的字符串
|
||||
*
|
||||
*
|
||||
* @param unicode Unicode符
|
||||
* @return String 字符串
|
||||
* @see UnicodeUtil#toString(String)
|
||||
@ -897,7 +897,7 @@ public class Convert {
|
||||
/**
|
||||
* 给定字符串转换字符编码<br>
|
||||
* 如果参数为空,则返回原字符串,不报错。
|
||||
*
|
||||
*
|
||||
* @param str 被转码的字符串
|
||||
* @param sourceCharset 原字符集
|
||||
* @param destCharset 目标字符集
|
||||
@ -914,7 +914,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换时间单位
|
||||
*
|
||||
*
|
||||
* @param sourceDuration 时长
|
||||
* @param sourceUnit 源单位
|
||||
* @param destUnit 目标单位
|
||||
@ -929,7 +929,7 @@ public class Convert {
|
||||
// --------------------------------------------------------------- 原始包装类型转换
|
||||
/**
|
||||
* 原始类转为包装类,非原始类返回原类
|
||||
*
|
||||
*
|
||||
* @see BasicType#wrap(Class)
|
||||
* @param clazz 原始类
|
||||
* @return 包装类
|
||||
@ -941,7 +941,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 包装类转为原始类,非包装类返回原类
|
||||
*
|
||||
*
|
||||
* @see BasicType#unWrap(Class)
|
||||
* @param clazz 包装类
|
||||
* @return 原始类
|
||||
@ -954,7 +954,7 @@ public class Convert {
|
||||
// -------------------------------------------------------------------------- 数字和英文转换
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达方式
|
||||
*
|
||||
*
|
||||
* @param number {@link Number}对象
|
||||
* @return 英文表达式
|
||||
* @since 3.0.9
|
||||
@ -962,10 +962,25 @@ public class Convert {
|
||||
public static String numberToWord(Number number) {
|
||||
return NumberWordFormatter.format(number);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为精简表示形式,例如:
|
||||
*
|
||||
* <pre>
|
||||
* 1200 -》 1.2k
|
||||
* </pre>
|
||||
*
|
||||
* @param number {@link Number}对象
|
||||
* @return 英文表达式
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public static String numberToSimple(Number number) {
|
||||
return NumberWordFormatter.formatSimple(number.longValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为中文表达方式
|
||||
*
|
||||
*
|
||||
* @param number 数字
|
||||
* @param isUseTraditonal 是否使用繁体字(金额形式)
|
||||
* @return 中文
|
||||
@ -974,10 +989,10 @@ public class Convert {
|
||||
public static String numberToChinese(double number, boolean isUseTraditonal) {
|
||||
return NumberChineseFormatter.format(number, isUseTraditonal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 金额转为中文形式
|
||||
*
|
||||
*
|
||||
* @param n 数字
|
||||
* @return 中文大写数字
|
||||
* @since 3.2.3
|
||||
@ -988,11 +1003,11 @@ public class Convert {
|
||||
}
|
||||
return NumberChineseFormatter.format(n.doubleValue(), true, true);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------- 数字转换
|
||||
/**
|
||||
* int转byte
|
||||
*
|
||||
*
|
||||
* @param intValue int值
|
||||
* @return byte值
|
||||
* @since 3.2.0
|
||||
@ -1003,7 +1018,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte转无符号int
|
||||
*
|
||||
*
|
||||
* @param byteValue byte值
|
||||
* @return 无符号int值
|
||||
* @since 3.2.0
|
||||
@ -1015,7 +1030,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte数组转short
|
||||
*
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @return short值
|
||||
* @since 3.2.0
|
||||
@ -1039,7 +1054,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte[]转int值
|
||||
*
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @return int值
|
||||
* @since 3.2.0
|
||||
@ -1053,7 +1068,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* int转byte数组
|
||||
*
|
||||
*
|
||||
* @param intValue int值
|
||||
* @return byte数组
|
||||
* @since 3.2.0
|
||||
@ -1070,7 +1085,7 @@ public class Convert {
|
||||
/**
|
||||
* long转byte数组<br>
|
||||
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||
*
|
||||
*
|
||||
* @param longValue long值
|
||||
* @return byte数组
|
||||
* @since 3.2.0
|
||||
@ -1088,7 +1103,7 @@ public class Convert {
|
||||
/**
|
||||
* byte数组转long<br>
|
||||
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||
*
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @return long值
|
||||
* @since 3.2.0
|
||||
|
@ -1,180 +1,182 @@
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* 将浮点数类型的number转换成英语的表达方式 <br>
|
||||
* 参考博客:http://blog.csdn.net/eric_sunah/article/details/8713226
|
||||
*
|
||||
* @author Looly
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public class NumberWordFormatter {
|
||||
|
||||
private static final String[] NUMBER = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
|
||||
"EIGHT", "NINE"};
|
||||
private static final String[] NUMBER_TEEN = new String[]{"TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN",
|
||||
"FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"};
|
||||
private static final String[] NUMBER_TEN = new String[]{"TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY",
|
||||
"SEVENTY", "EIGHTY", "NINETY"};
|
||||
private static final String[] NUMBER_MORE = new String[]{"", "THOUSAND", "MILLION", "BILLION"};
|
||||
|
||||
private static final String[] NUMBER_SUFFIX = new String[]{"k", "w", "", "m", "", "", "b", "", "", "t", "", "", "p", "", "", "e"};
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字,可以为{@link Number}对象,也可以是普通对象,最后会使用字符串方式处理
|
||||
* @return 英文表达式
|
||||
*/
|
||||
public static String format(Object x) {
|
||||
if (x != null) {
|
||||
return format(x.toString());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简介计数单位,例如 2100 => 2.1k
|
||||
* 范围默认只到w
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String formatValue(long value) {
|
||||
return formatValue(value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简介计数单位,例如 2100 => 2.1k
|
||||
* @param value 对应数字的值
|
||||
* @param isTwo 控制是否为k、w
|
||||
* @return
|
||||
*/
|
||||
public static String formatValue(long value, boolean isTwo) {
|
||||
if (value < 1000) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
int index = -1;
|
||||
double res = value * 1.0d;
|
||||
while (res > 10 && (!isTwo || index < 1)) {
|
||||
if (res > 1000) {
|
||||
res = res / 1000;
|
||||
index++;
|
||||
}
|
||||
if (res > 10) {
|
||||
res = res / 10;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||
return String.format("%s%s", decimalFormat.format(res), NUMBER_SUFFIX[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字字符串
|
||||
* @return 英文表达式
|
||||
*/
|
||||
private static String format(String x) {
|
||||
int z = x.indexOf("."); // 取小数点位置
|
||||
String lstr, rstr = "";
|
||||
if (z > -1) { // 看是否有小数,如果有,则分别取左边和右边
|
||||
lstr = x.substring(0, z);
|
||||
rstr = x.substring(z + 1);
|
||||
} else {
|
||||
// 否则就是全部
|
||||
lstr = x;
|
||||
}
|
||||
|
||||
String lstrrev = StrUtil.reverse(lstr); // 对左边的字串取反
|
||||
String[] a = new String[5]; // 定义5个字串变量来存放解析出来的叁位一组的字串
|
||||
|
||||
switch (lstrrev.length() % 3) {
|
||||
case 1:
|
||||
lstrrev += "00";
|
||||
break;
|
||||
case 2:
|
||||
lstrrev += "0";
|
||||
break;
|
||||
}
|
||||
StringBuilder lm = new StringBuilder(); // 用来存放转换后的整数部分
|
||||
for (int i = 0; i < lstrrev.length() / 3; i++) {
|
||||
a[i] = StrUtil.reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一个三位
|
||||
if (false == "000".equals(a[i])) { // 用来避免这种情况:1000000 = one million
|
||||
// thousand only
|
||||
if (i != 0) {
|
||||
lm.insert(0, transThree(a[i]) + " " + parseMore(i) + " "); // 加:
|
||||
// thousand、million、billion
|
||||
} else {
|
||||
// 防止i=0时, 在多加两个空格.
|
||||
lm = new StringBuilder(transThree(a[i]));
|
||||
}
|
||||
} else {
|
||||
lm.append(transThree(a[i]));
|
||||
}
|
||||
}
|
||||
|
||||
String xs = ""; // 用来存放转换后小数部分
|
||||
if (z > -1) {
|
||||
xs = "AND CENTS " + transTwo(rstr) + " "; // 小数部分存在时转换小数
|
||||
}
|
||||
|
||||
return lm.toString().trim() + " " + xs + "ONLY";
|
||||
}
|
||||
|
||||
private static String parseFirst(String s) {
|
||||
return NUMBER[Integer.parseInt(s.substring(s.length() - 1))];
|
||||
}
|
||||
|
||||
private static String parseTeen(String s) {
|
||||
return NUMBER_TEEN[Integer.parseInt(s) - 10];
|
||||
}
|
||||
|
||||
private static String parseTen(String s) {
|
||||
return NUMBER_TEN[Integer.parseInt(s.substring(0, 1)) - 1];
|
||||
}
|
||||
|
||||
private static String parseMore(int i) {
|
||||
return NUMBER_MORE[i];
|
||||
}
|
||||
|
||||
// 两位
|
||||
private static String transTwo(String s) {
|
||||
String value;
|
||||
// 判断位数
|
||||
if (s.length() > 2) {
|
||||
s = s.substring(0, 2);
|
||||
} else if (s.length() < 2) {
|
||||
s = "0" + s;
|
||||
}
|
||||
|
||||
if (s.startsWith("0")) {// 07 - seven 是否小於10
|
||||
value = parseFirst(s);
|
||||
} else if (s.startsWith("1")) {// 17 seventeen 是否在10和20之间
|
||||
value = parseTeen(s);
|
||||
} else if (s.endsWith("0")) {// 是否在10与100之间的能被10整除的数
|
||||
value = parseTen(s);
|
||||
} else {
|
||||
value = parseTen(s) + " " + parseFirst(s);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// 制作叁位的数
|
||||
// s.length = 3
|
||||
private static String transThree(String s) {
|
||||
String value;
|
||||
if (s.startsWith("0")) {// 是否小於100
|
||||
value = transTwo(s.substring(1));
|
||||
} else if ("00".equals(s.substring(1))) {// 是否被100整除
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED";
|
||||
} else {
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED AND " + transTwo(s.substring(1));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 将浮点数类型的number转换成英语的表达方式 <br>
|
||||
* 参考博客:http://blog.csdn.net/eric_sunah/article/details/8713226
|
||||
*
|
||||
* @author Looly,totalo
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public class NumberWordFormatter {
|
||||
|
||||
private static final String[] NUMBER = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
|
||||
"EIGHT", "NINE"};
|
||||
private static final String[] NUMBER_TEEN = new String[]{"TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN",
|
||||
"FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"};
|
||||
private static final String[] NUMBER_TEN = new String[]{"TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY",
|
||||
"SEVENTY", "EIGHTY", "NINETY"};
|
||||
private static final String[] NUMBER_MORE = new String[]{"", "THOUSAND", "MILLION", "BILLION"};
|
||||
|
||||
private static final String[] NUMBER_SUFFIX = new String[]{"k", "w", "", "m", "", "", "b", "", "", "t", "", "", "p", "", "", "e"};
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字,可以为{@link Number}对象,也可以是普通对象,最后会使用字符串方式处理
|
||||
* @return 英文表达式
|
||||
*/
|
||||
public static String format(Object x) {
|
||||
if (x != null) {
|
||||
return format(x.toString());
|
||||
} else {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简洁计数单位,例如 2100 =》 2.1k
|
||||
* 范围默认只到w
|
||||
*
|
||||
* @param value 被格式化的数字
|
||||
* @return 格式化后的数字
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public static String formatSimple(long value) {
|
||||
return formatSimple(value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简介计数单位,例如 2100 =》 2.1k
|
||||
*
|
||||
* @param value 对应数字的值
|
||||
* @param isTwo 控制是否为只为k、w,例如当为{@code false}时返回4.38m,{@code true}返回438.43w
|
||||
* @return 格式化后的数字
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public static String formatSimple(long value, boolean isTwo) {
|
||||
if (value < 1000) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
int index = -1;
|
||||
double res = value;
|
||||
while (res > 10 && (false == isTwo || index < 1)) {
|
||||
if (res > 1000) {
|
||||
res = res / 1000;
|
||||
index++;
|
||||
}
|
||||
if (res > 10) {
|
||||
res = res / 10;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return String.format("%s%s", NumberUtil.decimalFormat("#.##", res), NUMBER_SUFFIX[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字字符串
|
||||
* @return 英文表达式
|
||||
*/
|
||||
private static String format(String x) {
|
||||
int z = x.indexOf("."); // 取小数点位置
|
||||
String lstr, rstr = "";
|
||||
if (z > -1) { // 看是否有小数,如果有,则分别取左边和右边
|
||||
lstr = x.substring(0, z);
|
||||
rstr = x.substring(z + 1);
|
||||
} else {
|
||||
// 否则就是全部
|
||||
lstr = x;
|
||||
}
|
||||
|
||||
String lstrrev = StrUtil.reverse(lstr); // 对左边的字串取反
|
||||
String[] a = new String[5]; // 定义5个字串变量来存放解析出来的叁位一组的字串
|
||||
|
||||
switch (lstrrev.length() % 3) {
|
||||
case 1:
|
||||
lstrrev += "00";
|
||||
break;
|
||||
case 2:
|
||||
lstrrev += "0";
|
||||
break;
|
||||
}
|
||||
StringBuilder lm = new StringBuilder(); // 用来存放转换后的整数部分
|
||||
for (int i = 0; i < lstrrev.length() / 3; i++) {
|
||||
a[i] = StrUtil.reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一个三位
|
||||
if (false == "000".equals(a[i])) { // 用来避免这种情况:1000000 = one million
|
||||
// thousand only
|
||||
if (i != 0) {
|
||||
lm.insert(0, transThree(a[i]) + " " + parseMore(i) + " "); // 加:
|
||||
// thousand、million、billion
|
||||
} else {
|
||||
// 防止i=0时, 在多加两个空格.
|
||||
lm = new StringBuilder(transThree(a[i]));
|
||||
}
|
||||
} else {
|
||||
lm.append(transThree(a[i]));
|
||||
}
|
||||
}
|
||||
|
||||
String xs = ""; // 用来存放转换后小数部分
|
||||
if (z > -1) {
|
||||
xs = "AND CENTS " + transTwo(rstr) + " "; // 小数部分存在时转换小数
|
||||
}
|
||||
|
||||
return lm.toString().trim() + " " + xs + "ONLY";
|
||||
}
|
||||
|
||||
private static String parseFirst(String s) {
|
||||
return NUMBER[Integer.parseInt(s.substring(s.length() - 1))];
|
||||
}
|
||||
|
||||
private static String parseTeen(String s) {
|
||||
return NUMBER_TEEN[Integer.parseInt(s) - 10];
|
||||
}
|
||||
|
||||
private static String parseTen(String s) {
|
||||
return NUMBER_TEN[Integer.parseInt(s.substring(0, 1)) - 1];
|
||||
}
|
||||
|
||||
private static String parseMore(int i) {
|
||||
return NUMBER_MORE[i];
|
||||
}
|
||||
|
||||
// 两位
|
||||
private static String transTwo(String s) {
|
||||
String value;
|
||||
// 判断位数
|
||||
if (s.length() > 2) {
|
||||
s = s.substring(0, 2);
|
||||
} else if (s.length() < 2) {
|
||||
s = "0" + s;
|
||||
}
|
||||
|
||||
if (s.startsWith("0")) {// 07 - seven 是否小於10
|
||||
value = parseFirst(s);
|
||||
} else if (s.startsWith("1")) {// 17 seventeen 是否在10和20之间
|
||||
value = parseTeen(s);
|
||||
} else if (s.endsWith("0")) {// 是否在10与100之间的能被10整除的数
|
||||
value = parseTen(s);
|
||||
} else {
|
||||
value = parseTen(s) + " " + parseFirst(s);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// 制作叁位的数
|
||||
// s.length = 3
|
||||
private static String transThree(String s) {
|
||||
String value;
|
||||
if (s.startsWith("0")) {// 是否小於100
|
||||
value = transTwo(s.substring(1));
|
||||
} else if ("00".equals(s.substring(1))) {// 是否被100整除
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED";
|
||||
} else {
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED AND " + transTwo(s.substring(1));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
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