This commit is contained in:
Looly 2023-03-13 05:04:50 +08:00
parent 5b559d19bd
commit 48eec2a8ae
92 changed files with 1487 additions and 651 deletions

View File

@ -17,6 +17,69 @@
<description>Hutool是一个优雅而小巧的Java工具类库</description>
<url>https://github.com/looly/hutool</url>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-db</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-log</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-setting</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-cron</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-poi</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-socket</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-swing</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>

View File

@ -42,6 +42,9 @@ import java.util.Set;
*/
public class Hutool {
/**
* 作者贡献者
*/
public static final String AUTHOR = "Looly";
private Hutool() {

View File

@ -703,7 +703,7 @@ public class AnnotatedElementUtil {
/**
* 清空相关缓存包括
* <ul>
* <li>{@link AnnotatedElementUtil}中的{@link AnnotatedElement}{@link AnnotationMapping}缓存</li>
* <li>{@code AnnotatedElementUtil}中的{@link AnnotatedElement}{@link AnnotationMapping}缓存</li>
* <li>{@link AnnotationUtil}中的{@link AnnotatedElement}上直接声明的注解缓存</li>
* <li>{@link RepeatableAnnotationCollector}中单例的注解属性缓存</li>
* </ul>

View File

@ -25,7 +25,7 @@ public interface RepeatableAnnotationCollector {
/**
* 空实现
*
* @return {@link RepeatableAnnotationCollector}实例
* @return {@code RepeatableAnnotationCollector}实例
*/
static RepeatableAnnotationCollector none() {
return None.INSTANCE;
@ -47,7 +47,7 @@ public interface RepeatableAnnotationCollector {
* </code></pre>
* 解析任意{@code Annotation}注解对象则可以获得{@code value}属性中的{@code Item}注解对象
*
* @return {@link RepeatableAnnotationCollector}实例
* @return {@code RepeatableAnnotationCollector}实例
* @see Standard
*/
static RepeatableAnnotationCollector standard() {
@ -59,7 +59,7 @@ public interface RepeatableAnnotationCollector {
* 收集器将返回所有匹配的属性中的可重复注解
*
* @param predicate 是否为容纳可重复注解的属性的判断条件
* @return {@link RepeatableAnnotationCollector}实例
* @return {@code RepeatableAnnotationCollector}实例
*/
static RepeatableAnnotationCollector condition(final BiPredicate<Annotation, Method> predicate) {
return new Condition(predicate);
@ -80,7 +80,7 @@ public interface RepeatableAnnotationCollector {
* 则可以获得{@code items1}属性中的{@code Item1}注解对象
* 以及{@code items2}属性中的{@code Item2}注解对象
*
* @return {@link RepeatableAnnotationCollector}实例
* @return {@code RepeatableAnnotationCollector}实例
*/
static RepeatableAnnotationCollector full() {
return Full.INSTANCE;
@ -189,7 +189,7 @@ public interface RepeatableAnnotationCollector {
}
/**
* {@link RepeatableAnnotationCollector}的基本实现
* {@code RepeatableAnnotationCollector}的基本实现
*/
abstract class AbstractCollector implements RepeatableAnnotationCollector {
@ -218,7 +218,7 @@ public interface RepeatableAnnotationCollector {
* @return 容器注解中的可重复注解{@code annotation}不为容器注解则数组中仅有其本身一个对象
*/
@Override
public List<Annotation> getAllRepeatableAnnotations(Annotation annotation) {
public List<Annotation> getAllRepeatableAnnotations(final Annotation annotation) {
return find(annotation, null, true);
}
@ -261,7 +261,7 @@ public interface RepeatableAnnotationCollector {
final boolean isTarget = hasCondition && condition.test(source);
if (CollUtil.isEmpty(repeatableMethods) || isTarget) {
// 不是累加的则仅当正在处理的注解不为可重复注解时才记录
boolean shouldProcess = !accumulate && (!hasCondition || isTarget);
final boolean shouldProcess = !accumulate && (!hasCondition || isTarget);
if (shouldProcess) {
results.add(source);
}

View File

@ -145,10 +145,10 @@ public class ResolvedAnnotationMapping implements AnnotationMapping<Annotation>
* <ul>
* <li>{@code annotation}已经被代理过时抛出</li>
* <li>{@code source}包装的注解对象与{@code annotation}相同时抛出</li>
* <li>{@code annotation}包装的注解对象类型为{@link ResolvedAnnotationMapping}时抛出</li>
* <li>{@code annotation}包装的注解对象类型为{@code ResolvedAnnotationMapping}时抛出</li>
* </ul>
*/
ResolvedAnnotationMapping(final ResolvedAnnotationMapping source, final Annotation annotation, boolean resolveAttribute) {
ResolvedAnnotationMapping(final ResolvedAnnotationMapping source, final Annotation annotation, final boolean resolveAttribute) {
Objects.requireNonNull(annotation);
Assert.isFalse(AnnotationMappingProxy.isProxied(annotation), "annotation has been proxied");
Assert.isFalse(annotation instanceof ResolvedAnnotationMapping, "annotation has been wrapped");
@ -254,7 +254,6 @@ public class ResolvedAnnotationMapping implements AnnotationMapping<Annotation>
*
* @return 所需的注解{@link ResolvedAnnotationMapping#isResolved()}{@code false}则返回的是原始的注解对象
*/
@SuppressWarnings("unchecked")
@Override
public Annotation getResolvedAnnotation() {
if (!isResolved()) {
@ -399,7 +398,7 @@ public class ResolvedAnnotationMapping implements AnnotationMapping<Annotation>
}
// 获取除自己外的全部子注解
final Deque<ResolvedAnnotationMapping> sources = new LinkedList<>();
Set<Class<? extends Annotation>> accessed = new HashSet<>();
final Set<Class<? extends Annotation>> accessed = new HashSet<>();
accessed.add(this.annotationType());
ResolvedAnnotationMapping sourceMapping = this.source;
while (Objects.nonNull(sourceMapping)) {
@ -444,7 +443,7 @@ public class ResolvedAnnotationMapping implements AnnotationMapping<Annotation>
* 更新需要覆写的属性的相关映射关系若该属性存在别名则将别名的映射关系一并覆写
*/
private void overwriteAttribute(
final ResolvedAnnotationMapping overwriteMapping, final int overwriteIndex, final int targetIndex, boolean overwriteAliases) {
final ResolvedAnnotationMapping overwriteMapping, final int overwriteIndex, final int targetIndex, final boolean overwriteAliases) {
// 若目标属性已被覆写则不允许再次覆写
if (isOverwrittenAttribute(targetIndex)) {
return;
@ -463,7 +462,7 @@ public class ResolvedAnnotationMapping implements AnnotationMapping<Annotation>
/**
* 判断该属性是否已被覆写
*/
private boolean isOverwrittenAttribute(int index) {
private boolean isOverwrittenAttribute(final int index) {
// 若属性未发生过解析则必然未被覆写
return NOT_FOUND_INDEX != resolvedAttributes[index]
// 若属性发生过解析且指向其他实例则说明已被覆写
@ -567,14 +566,14 @@ public class ResolvedAnnotationMapping implements AnnotationMapping<Annotation>
* @return 是否
*/
@Override
public boolean equals(Object o) {
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ResolvedAnnotationMapping that = (ResolvedAnnotationMapping)o;
final ResolvedAnnotationMapping that = (ResolvedAnnotationMapping)o;
return resolved == that.resolved && annotation.equals(that.annotation);
}
@ -671,8 +670,8 @@ public class ResolvedAnnotationMapping implements AnnotationMapping<Annotation>
/**
* 遍历下标
*/
void forEach(IntConsumer consumer) {
for (int index : indexes) {
void forEach(final IntConsumer consumer) {
for (final int index : indexes) {
consumer.accept(index);
}
}

View File

@ -20,6 +20,13 @@ public abstract class AbsCopier<S, T> implements Copier<T> {
*/
protected final CopyOptions copyOptions;
/**
* 构造
*
* @param source 源对象
* @param target 目标对象
* @param copyOptions 拷贝选项
*/
public AbsCopier(final S source, final T target, final CopyOptions copyOptions) {
this.source = source;
this.target = target;

View File

@ -31,7 +31,7 @@ public class HexUtil {
* @return 是否为16进制
*/
public static boolean isHexNumber(final String value) {
if(StrUtil.startWith(value, '-')){
if (StrUtil.startWith(value, '-')) {
// issue#2875
return false;
}
@ -39,7 +39,7 @@ public class HexUtil {
if (value.startsWith("0x", index) || value.startsWith("0X", index)) {
index += 2;
} else if (value.startsWith("#", index)) {
index ++;
index++;
}
try {
new BigInteger(value.substring(index), 16);
@ -253,7 +253,7 @@ public class HexUtil {
* 转换的字符串如果u后不足4位则前面用0填充例如
*
* <pre>
* '你' =\u4f60
* = &#92;u4f60
* </pre>
*
* @param value int值也可以是char
@ -278,7 +278,7 @@ public class HexUtil {
* 转换的字符串如果u后不足4位则前面用0填充例如
*
* <pre>
* '你' ='\u4f60'
* = &#92;u4f60
* </pre>
*
* @param ch char值

View File

@ -81,7 +81,7 @@ public class Base16Codec implements Encoder<byte[], char[]>, Decoder<CharSequenc
* 转换的字符串如果u后不足4位则前面用0填充例如
*
* <pre>
* '你' ='&#92;u4f60'
* =&#92;u4f60
* </pre>
*
* @param ch char值

View File

@ -69,7 +69,13 @@ public class Base32Codec implements Encoder<byte[], String>, Decoder<CharSequenc
private static final Character DEFAULT_PAD = '=';
private static final int[] BASE32_FILL = {-1, 4, 1, 6, 3};
/**
* 编码器
*/
public static final Base32Encoder ENCODER = new Base32Encoder(DEFAULT_ALPHABET, DEFAULT_PAD);
/**
* 16进制编码器
*/
public static final Base32Encoder HEX_ENCODER = new Base32Encoder(HEX_ALPHABET, DEFAULT_PAD);
private final char[] alphabet;
@ -145,7 +151,13 @@ public class Base32Codec implements Encoder<byte[], String>, Decoder<CharSequenc
public static class Base32Decoder implements Decoder<CharSequence, byte[]> {
private static final char BASE_CHAR = '0';
/**
* 解码器
*/
public static final Base32Decoder DECODER = new Base32Decoder(Base32Encoder.DEFAULT_ALPHABET);
/**
* 16进制解码器
*/
public static final Base32Decoder HEX_DECODER = new Base32Decoder(Base32Encoder.HEX_ALPHABET);
private final byte[] lookupTable;
@ -166,7 +178,7 @@ public class Base32Codec implements Encoder<byte[], String>, Decoder<CharSequenc
c = alphabet.charAt(i);
lookupTable[c - BASE_CHAR] = (byte) i;
// 支持小写字母解码
if(c >= 'A' && c <= 'Z'){
if (c >= 'A' && c <= 'Z') {
lookupTable[Character.toLowerCase(c) - BASE_CHAR] = (byte) i;
}
}

View File

@ -15,6 +15,9 @@ import java.util.Arrays;
*/
public class Base58Codec implements Encoder<byte[], String>, Decoder<CharSequence, byte[]> {
/**
* 单例
*/
public static Base58Codec INSTANCE = new Base58Codec();
/**
@ -48,6 +51,9 @@ public class Base58Codec implements Encoder<byte[], String>, Decoder<CharSequenc
public static class Base58Encoder implements Encoder<byte[], String> {
private static final String DEFAULT_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
/**
* 编码器
*/
public static final Base58Encoder ENCODER = new Base58Encoder(DEFAULT_ALPHABET.toCharArray());
private final char[] alphabet;
@ -105,6 +111,9 @@ public class Base58Codec implements Encoder<byte[], String>, Decoder<CharSequenc
*/
public static class Base58Decoder implements Decoder<CharSequence, byte[]> {
/**
* 解码器
*/
public static Base58Decoder DECODER = new Base58Decoder(Base58Encoder.DEFAULT_ALPHABET);
private final byte[] lookupTable;

View File

@ -20,6 +20,9 @@ public class Base62Codec implements Encoder<byte[], byte[]>, Decoder<byte[], byt
private static final int STANDARD_BASE = 256;
private static final int TARGET_BASE = 62;
/**
* 单例
*/
public static Base62Codec INSTANCE = new Base62Codec();
/**
@ -102,7 +105,13 @@ public class Base62Codec implements Encoder<byte[], byte[]>, Decoder<byte[], byt
'U', 'V', 'W', 'X', 'Y', 'Z' //
};
/**
* GMP风格编码器
*/
public static Base62Encoder GMP_ENCODER = new Base62Encoder(GMP);
/**
* 反转风格即将GMP风格中的大小写做转换编码器
*/
public static Base62Encoder INVERTED_ENCODER = new Base62Encoder(INVERTED);
private final byte[] alphabet;
@ -130,7 +139,13 @@ public class Base62Codec implements Encoder<byte[], byte[]>, Decoder<byte[], byt
*/
public static class Base62Decoder implements Decoder<byte[], byte[]> {
/**
* GMP风格解码器
*/
public static Base62Decoder GMP_DECODER = new Base62Decoder(Base62Encoder.GMP);
/**
* 反转风格即将GMP风格中的大小写做转换解码器
*/
public static Base62Decoder INVERTED_DECODER = new Base62Decoder(Base62Encoder.INVERTED);
private final byte[] lookupTable;

View File

@ -1,6 +1,8 @@
package cn.hutool.core.codec.hash;
import cn.hutool.core.codec.Number128;
import cn.hutool.core.codec.hash.metro.MetroHash128;
import cn.hutool.core.codec.hash.metro.MetroHash64;
/**
* Hash算法大全<br>
@ -554,17 +556,7 @@ public class HashUtil {
* @return hash值
*/
public static long metroHash64(final byte[] data, final long seed) {
return MetroHash.INSTANCE.hash64(data, seed);
}
/**
* MetroHash 算法64-bit实现
*
* @param data 数据
* @return hash值
*/
public static long metroHash64(final byte[] data) {
return MetroHash.INSTANCE.hash64(data);
return MetroHash64.of(seed).hash64(data);
}
/**
@ -575,17 +567,7 @@ public class HashUtil {
* @return hash值long[0]低位long[1]高位
*/
public static long[] metroHash128(final byte[] data, final long seed) {
return MetroHash.INSTANCE.hash128(data, seed).getLongArray();
}
/**
* MetroHash 算法128-bit实现
*
* @param data 数据
* @return hash值long[0]低位long[1]高位
*/
public static long[] metroHash128(final byte[] data) {
return MetroHash.INSTANCE.hash128(data).getLongArray();
return MetroHash128.of(seed).hash128(data).getLongArray();
}
/**

View File

@ -1,237 +0,0 @@
package cn.hutool.core.codec.hash;
import cn.hutool.core.codec.Number128;
import cn.hutool.core.util.ByteUtil;
import java.nio.ByteOrder;
import java.util.Arrays;
/**
* Apache 发布的MetroHash算法是一组用于非加密用例的最先进的哈希函数
* 除了卓越的性能外他们还以算法生成而著称
*
* <p>
* 官方实现https://github.com/jandrewrogers/MetroHash
* 官方文档http://www.jandrewrogers.com/2015/05/27/metrohash/
* Go语言实现https://github.com/linvon/cuckoo-filter/blob/main/vendor/github.com/dgryski/go-metro/
*
* @author li
*/
public class MetroHash implements Hash64<byte[]>, Hash128<byte[]> {
public static MetroHash INSTANCE = new MetroHash();
@Override
public Number encode(final byte[] bytes) {
return hash64(bytes);
}
@Override
public long hash64(final byte[] data) {
return hash64(data, 1337);
}
/**
* 计算64位Hash值
*
* @param data 数据
* @param seed 种子
* @return hash64
*/
public long hash64(final byte[] data, final long seed) {
final long k0_64 = 0xD6D018F5;
final long k1_64 = 0xA2AA033B;
final long k2_64 = 0x62992FC1;
final long k3_64 = 0x30BC5B29;
byte[] buffer = data;
long hash = (seed + k2_64) * k0_64;
long v0, v1, v2, v3;
v0 = hash;
v1 = hash;
v2 = hash;
v3 = hash;
if (buffer.length >= 32) {
while (buffer.length >= 32) {
v0 += littleEndian64(buffer, 0) * k0_64;
v0 = rotateLeft64(v0, -29) + v2;
v1 += littleEndian64(buffer, 8) * k1_64;
v1 = rotateLeft64(v1, -29) + v3;
v2 += littleEndian64(buffer, 24) * k2_64;
v2 = rotateLeft64(v2, -29) + v0;
v3 += littleEndian64(buffer, 32) * k3_64;
v3 = rotateLeft64(v3, -29) + v1;
buffer = Arrays.copyOfRange(buffer, 32, buffer.length);
}
v2 ^= rotateLeft64(((v0 + v3) * k0_64) + v1, -37) * k1_64;
v3 ^= rotateLeft64(((v1 + v2) * k1_64) + v0, -37) * k0_64;
v0 ^= rotateLeft64(((v0 + v2) * k0_64) + v3, -37) * k1_64;
v1 ^= rotateLeft64(((v1 + v3) * k1_64) + v2, -37) * k0_64;
hash += v0 ^ v1;
}
if (buffer.length >= 16) {
v0 = hash + littleEndian64(buffer, 0) * k2_64;
v0 = rotateLeft64(v0, -29) * k3_64;
v1 = hash + littleEndian64(buffer, 8) * k2_64;
v1 = rotateLeft64(v1, -29) * k3_64;
v0 ^= rotateLeft64(v0 * k0_64, -21) + v1;
v1 ^= rotateLeft64(v1 * k3_64, -21) + v0;
hash += v1;
buffer = Arrays.copyOfRange(buffer, 16, buffer.length);
}
if (buffer.length >= 8) {
hash += littleEndian64(buffer, 0) * k3_64;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
hash ^= rotateLeft64(hash, -55) * k1_64;
}
if (buffer.length >= 4) {
hash += (long) littleEndian32(Arrays.copyOfRange(buffer, 0, 4)) * k3_64;
hash ^= rotateLeft64(hash, -26) * k1_64;
buffer = Arrays.copyOfRange(buffer, 4, buffer.length);
}
if (buffer.length >= 2) {
hash += (long) littleEndian16(Arrays.copyOfRange(buffer, 0, 2)) * k3_64;
buffer = Arrays.copyOfRange(buffer, 2, buffer.length);
hash ^= rotateLeft64(hash, -48) * k1_64;
}
if (buffer.length >= 1) {
hash += (long) buffer[0] * k3_64;
hash ^= rotateLeft64(hash, -38) * k1_64;
}
hash ^= rotateLeft64(hash, -28);
hash *= k0_64;
hash ^= rotateLeft64(hash, -29);
return hash;
}
@Override
public Number128 hash128(final byte[] data) {
return hash128(data, 1337);
}
/**
* 计算128位hash值
*
* @param data 数据
* @param seed 种子
* @return hash128
*/
public Number128 hash128(final byte[] data, final long seed) {
final long k0_128 = 0xC83A91E1;
final long k1_128 = 0x8648DBDB;
final long k2_128 = 0x7BDEC03B;
final long k3_128 = 0x2F5870A5;
byte[] buffer = data;
long v0, v1, v2, v3;
v0 = (seed - k0_128) * k3_128;
v1 = (seed + k1_128) * k2_128;
if (buffer.length >= 32) {
v2 = (seed + k0_128) * k2_128;
v3 = (seed - k1_128) * k3_128;
while (buffer.length >= 32) {
v0 += littleEndian64(buffer, 0) * k0_128;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
v0 = rotateRight(v0, 29) + v2;
v1 += littleEndian64(buffer, 0) * k1_128;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
v1 = rotateRight(v1, 29) + v3;
v2 += littleEndian64(buffer, 0) * k2_128;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
v2 = rotateRight(v2, 29) + v0;
v3 = littleEndian64(buffer, 0) * k3_128;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
v3 = rotateRight(v3, 29) + v1;
}
v2 ^= rotateRight(((v0 + v3) * k0_128) + v1, 21) * k1_128;
v3 ^= rotateRight(((v1 + v2) * k1_128) + v0, 21) * k0_128;
v0 ^= rotateRight(((v0 + v2) * k0_128) + v3, 21) * k1_128;
v1 ^= rotateRight(((v1 + v3) * k1_128) + v2, 21) * k0_128;
}
if (buffer.length >= 16) {
v0 += littleEndian64(buffer, 0) * k2_128;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
v0 = rotateRight(v0, 33) * k3_128;
v1 += littleEndian64(buffer, 0) * k2_128;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
v1 = rotateRight(v1, 33) * k3_128;
v0 ^= rotateRight((v0 * k2_128) + v1, 45) + k1_128;
v1 ^= rotateRight((v1 * k3_128) + v0, 45) + k0_128;
}
if (buffer.length >= 8) {
v0 += littleEndian64(buffer, 0) * k2_128;
buffer = Arrays.copyOfRange(buffer, 8, buffer.length);
v0 = rotateRight(v0, 33) * k3_128;
v0 ^= rotateRight((v0 * k2_128) + v1, 27) * k1_128;
}
if (buffer.length >= 4) {
v1 += (long) littleEndian32(buffer) * k2_128;
buffer = Arrays.copyOfRange(buffer, 4, buffer.length);
v1 = rotateRight(v1, 33) * k3_128;
v1 ^= rotateRight((v1 * k3_128) + v0, 46) * k0_128;
}
if (buffer.length >= 2) {
v0 += (long) littleEndian16(buffer) * k2_128;
buffer = Arrays.copyOfRange(buffer, 2, buffer.length);
v0 = rotateRight(v0, 33) * k3_128;
v0 ^= rotateRight((v0 * k2_128) * v1, 22) * k1_128;
}
if (buffer.length >= 1) {
v1 += (long) buffer[0] * k2_128;
v1 = rotateRight(v1, 33) * k3_128;
v1 ^= rotateRight((v1 * k3_128) + v0, 58) * k0_128;
}
v0 += rotateRight((v0 * k0_128) + v1, 13);
v1 += rotateRight((v1 * k1_128) + v0, 37);
v0 += rotateRight((v0 * k2_128) + v1, 13);
v1 += rotateRight((v1 * k3_128) + v0, 37);
return new Number128(v0, v1);
}
// region =========== Private methods
private static long littleEndian64(final byte[] b, final int start) {
return ByteUtil.bytesToLong(b, start, ByteOrder.LITTLE_ENDIAN);
}
private static int littleEndian32(final byte[] b) {
return (int) b[0] | (int) b[1] << 8 | (int) b[2] << 16 | (int) b[3] << 24;
}
private static int littleEndian16(final byte[] b) {
return ByteUtil.bytesToShort(b, ByteOrder.LITTLE_ENDIAN);
}
private static long rotateLeft64(final long x, final int k) {
final int n = 64;
final int s = k & (n - 1);
return x << s | x >> (n - s);
}
private static long rotateRight(final long val, final int shift) {
return (val >> shift) | (val << (64 - shift));
}
// endregion =========== Private methods
}

View File

@ -0,0 +1,63 @@
package cn.hutool.core.codec.hash.metro;
import java.nio.ByteBuffer;
/**
* Apache 发布的MetroHash算法抽象实现是一组用于非加密用例的最先进的哈希函数
* 除了卓越的性能外他们还以算法生成而著称
*
* <p>
* 官方实现https://github.com/jandrewrogers/MetroHash
* 官方文档http://www.jandrewrogers.com/2015/05/27/metrohash/
* 来自https://github.com/postamar/java-metrohash/
*
* @author Marius Posta
* @param <R> 返回值类型为this类型
*/
public abstract class AbstractMetroHash<R extends AbstractMetroHash<R>> implements MetroHash<R> {
final long seed;
long v0, v1, v2, v3;
long nChunks;
/**
* 使用指定种子构造
*
* @param seed 种子
*/
public AbstractMetroHash(final long seed) {
this.seed = seed;
reset();
}
/**
* Applies the instance's Metro hash function to the bytes in the given buffer.
* This updates this instance's hashing state.
*
* @param input 内容
* @return this
*/
public R apply(final ByteBuffer input) {
reset();
while (input.remaining() >= 32) {
partialApply32ByteChunk(input);
}
return partialApplyRemaining(input);
}
/**
* Consumes a 32-byte chunk from the byte buffer and updates the hashing state.
*
* @param partialInput byte buffer with at least 32 bytes remaining.
* @return this
*/
abstract R partialApply32ByteChunk(ByteBuffer partialInput);
/**
* Consumes the remaining bytes from the byte buffer and updates the hashing state.
*
* @param partialInput byte buffer with less than 32 bytes remaining.
* @return this
*/
abstract R partialApplyRemaining(ByteBuffer partialInput);
}

View File

@ -0,0 +1,56 @@
package cn.hutool.core.codec.hash.metro;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Apache 发布的MetroHash算法接口是一组用于非加密用例的最先进的哈希函数
* 除了卓越的性能外他们还以算法生成而著称
*
* <p>
* 官方实现https://github.com/jandrewrogers/MetroHash
* 官方文档http://www.jandrewrogers.com/2015/05/27/metrohash/
* 来自https://github.com/postamar/java-metrohash/
*
* @param <R> 返回值类型为this类型
* @author Marius Posta
*/
public interface MetroHash<R extends MetroHash<R>> {
/**
* 创建 {@code MetroHash}对象
*
* @param seed 种子
* @param is128 是否128位
* @return {@code MetroHash}对象
*/
static MetroHash<?> of(final long seed, final boolean is128) {
return is128 ? new MetroHash128(seed) : new MetroHash64(seed);
}
/**
* Applies the instance's Metro hash function to the bytes in the given buffer.
* This updates this instance's hashing state.
*
* @param input 内容
* @return this
*/
R apply(final ByteBuffer input);
/**
* Writes the current hash to the given byte buffer in big-endian order.
* 将结果hash值写出到{@link ByteBuffer}
*
* @param output 输出
* @param byteOrder 端序
* @return this
*/
R write(ByteBuffer output, final ByteOrder byteOrder);
/**
* 重置重置后可复用对象开启新的计算
*
* @return this
*/
R reset();
}

View File

@ -0,0 +1,182 @@
package cn.hutool.core.codec.hash.metro;
import cn.hutool.core.codec.Number128;
import cn.hutool.core.codec.hash.Hash128;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Apache 发布的MetroHash算法的128位实现是一组用于非加密用例的最先进的哈希函数
* 除了卓越的性能外他们还以算法生成而著称
*
* <p>
* 官方实现https://github.com/jandrewrogers/MetroHash
* 官方文档http://www.jandrewrogers.com/2015/05/27/metrohash/
* 来自https://github.com/postamar/java-metrohash/
* @author Marius Posta
*/
public class MetroHash128 extends AbstractMetroHash<MetroHash128> implements Hash128<byte[]> {
/**
* 创建 {@code MetroHash128}对象
*
* @param seed 种子
* @return {@code MetroHash128}对象
*/
public static MetroHash128 of(final long seed) {
return new MetroHash128(seed);
}
private static final long K0 = 0xC83A91E1L;
private static final long K1 = 0x8648DBDBL;
private static final long K2 = 0x7BDEC03BL;
private static final long K3 = 0x2F5870A5L;
/**
* 使用指定种子构造
*
* @param seed 种子
*/
public MetroHash128(final long seed) {
super(seed);
}
@Override
public MetroHash128 reset() {
v0 = (seed - K0) * K3;
v1 = (seed + K1) * K2;
v2 = (seed + K0) * K2;
v3 = (seed - K1) * K3;
nChunks = 0;
return this;
}
/**
* 获取高64位结果hash值
*
* @return hash值
*/
public long getHigh() {
return v0;
}
/**
* 获取低64位结果hash值
*
* @return hash值
*/
public long getLow() {
return v1;
}
/**
* 获取结果hash值
*
* @return hash值
*/
public Number128 get() {
return new Number128(v1, v0);
}
@Override
public Number128 hash128(final byte[] bytes) {
return apply(ByteBuffer.wrap(bytes)).get();
}
@Override
public MetroHash128 write(final ByteBuffer output, final ByteOrder byteOrder) {
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
MetroHashInternalUtil.writeLittleEndian(v0, output);
MetroHashInternalUtil.writeLittleEndian(v1, output);
} else {
output.asLongBuffer().put(v1).put(v0);
}
return this;
}
@Override
MetroHash128 partialApply32ByteChunk(final ByteBuffer partialInput) {
assert partialInput.remaining() >= 32;
v0 += MetroHashInternalUtil.grab8(partialInput) * K0;
v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2;
v1 += MetroHashInternalUtil.grab8(partialInput) * K1;
v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3;
v2 += MetroHashInternalUtil.grab8(partialInput) * K2;
v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0;
v3 += MetroHashInternalUtil.grab8(partialInput) * K3;
v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1;
++nChunks;
return this;
}
@Override
MetroHash128 partialApplyRemaining(final ByteBuffer partialInput) {
assert partialInput.remaining() < 32;
if (nChunks > 0) {
metroHash128_32();
}
if (partialInput.remaining() >= 16) {
metroHash128_16(partialInput);
}
if (partialInput.remaining() >= 8) {
metroHash128_8(partialInput);
}
if (partialInput.remaining() >= 4) {
metroHash128_4(partialInput);
}
if (partialInput.remaining() >= 2) {
metroHash128_2(partialInput);
}
if (partialInput.remaining() >= 1) {
metroHash128_1(partialInput);
}
v0 += MetroHashInternalUtil.rotateRight64(v0 * K0 + v1, 13);
v1 += MetroHashInternalUtil.rotateRight64(v1 * K1 + v0, 37);
v0 += MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 13);
v1 += MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 37);
return this;
}
// region ----- private methods
private void metroHash128_32() {
v2 ^= MetroHashInternalUtil.rotateRight64((v0 + v3) * K0 + v1, 21) * K1;
v3 ^= MetroHashInternalUtil.rotateRight64((v1 + v2) * K1 + v0, 21) * K0;
v0 ^= MetroHashInternalUtil.rotateRight64((v0 + v2) * K0 + v3, 21) * K1;
v1 ^= MetroHashInternalUtil.rotateRight64((v1 + v3) * K1 + v2, 21) * K0;
}
private void metroHash128_16(final ByteBuffer bb) {
v0 += MetroHashInternalUtil.grab8(bb) * K2;
v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3;
v1 += MetroHashInternalUtil.grab8(bb) * K2;
v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3;
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 45) * K1;
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 45) * K0;
}
private void metroHash128_8(final ByteBuffer bb) {
v0 += MetroHashInternalUtil.grab8(bb) * K2;
v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3;
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 27) * K1;
}
private void metroHash128_4(final ByteBuffer bb) {
v1 += MetroHashInternalUtil.grab4(bb) * K2;
v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3;
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 46) * K0;
}
private void metroHash128_2(final ByteBuffer bb) {
v0 += MetroHashInternalUtil.grab2(bb) * K2;
v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3;
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 22) * K1;
}
private void metroHash128_1(final ByteBuffer bb) {
v1 += MetroHashInternalUtil.grab1(bb) * K2;
v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3;
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 58) * K0;
}
// endregion
}

View File

@ -0,0 +1,158 @@
package cn.hutool.core.codec.hash.metro;
import cn.hutool.core.codec.hash.Hash64;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Apache 发布的MetroHash算法的64位实现是一组用于非加密用例的最先进的哈希函数
* 除了卓越的性能外他们还以算法生成而著称
*
* <p>
* 官方实现https://github.com/jandrewrogers/MetroHash
* 官方文档http://www.jandrewrogers.com/2015/05/27/metrohash/
* 来自https://github.com/postamar/java-metrohash/
* @author Marius Posta
*/
public class MetroHash64 extends AbstractMetroHash<MetroHash64> implements Hash64<byte[]> {
/**
* 创建 {@code MetroHash64}对象
*
* @param seed 种子
* @return {@code MetroHash64}对象
*/
public static MetroHash64 of(final long seed) {
return new MetroHash64(seed);
}
private static final long K0 = 0xD6D018F5L;
private static final long K1 = 0xA2AA033BL;
private static final long K2 = 0x62992FC1L;
private static final long K3 = 0x30BC5B29L;
private long hash;
/**
* 使用指定种子构造
*
* @param seed 种子
*/
public MetroHash64(final long seed) {
super(seed);
}
@Override
public MetroHash64 reset() {
v0 = v1 = v2 = v3 = hash = (seed + K2) * K0;
nChunks = 0;
return this;
}
/**
* 获取计算结果hash值
*
* @return hash值
*/
public long get() {
return hash;
}
@Override
public long hash64(final byte[] bytes) {
return apply(ByteBuffer.wrap(bytes)).get();
}
@Override
public MetroHash64 write(final ByteBuffer output, final ByteOrder byteOrder) {
if(ByteOrder.LITTLE_ENDIAN == byteOrder){
MetroHashInternalUtil.writeLittleEndian(hash, output);
} else{
output.asLongBuffer().put(hash);
}
return this;
}
@Override
MetroHash64 partialApply32ByteChunk(final ByteBuffer partialInput) {
assert partialInput.remaining() >= 32;
v0 += MetroHashInternalUtil.grab8(partialInput) * K0;
v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2;
v1 += MetroHashInternalUtil.grab8(partialInput) * K1;
v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3;
v2 += MetroHashInternalUtil.grab8(partialInput) * K2;
v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0;
v3 += MetroHashInternalUtil.grab8(partialInput) * K3;
v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1;
++nChunks;
return this;
}
@Override
MetroHash64 partialApplyRemaining(final ByteBuffer partialInput) {
assert partialInput.remaining() < 32;
if (nChunks > 0) {
metroHash64_32();
}
if (partialInput.remaining() >= 16) {
metroHash64_16(partialInput);
}
if (partialInput.remaining() >= 8) {
metroHash64_8(partialInput);
}
if (partialInput.remaining() >= 4) {
metroHash64_4(partialInput);
}
if (partialInput.remaining() >= 2) {
metroHash64_2(partialInput);
}
if (partialInput.remaining() >= 1) {
metroHash64_1(partialInput);
}
hash ^= MetroHashInternalUtil.rotateRight64(hash, 28);
hash *= K0;
hash ^= MetroHashInternalUtil.rotateRight64(hash, 29);
return this;
}
// region ----- private methods
private void metroHash64_32() {
v2 ^= MetroHashInternalUtil.rotateRight64(((v0 + v3) * K0) + v1, 37) * K1;
v3 ^= MetroHashInternalUtil.rotateRight64(((v1 + v2) * K1) + v0, 37) * K0;
v0 ^= MetroHashInternalUtil.rotateRight64(((v0 + v2) * K0) + v3, 37) * K1;
v1 ^= MetroHashInternalUtil.rotateRight64(((v1 + v3) * K1) + v2, 37) * K0;
hash += v0 ^ v1;
}
private void metroHash64_16(final ByteBuffer bb) {
v0 = hash + MetroHashInternalUtil.grab8(bb) * K2;
v0 = MetroHashInternalUtil.rotateRight64(v0, 29) * K3;
v1 = hash + MetroHashInternalUtil.grab8(bb) * K2;
v1 = MetroHashInternalUtil.rotateRight64(v1, 29) * K3;
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K0, 21) + v1;
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3, 21) + v0;
hash += v1;
}
private void metroHash64_8(final ByteBuffer bb) {
hash += MetroHashInternalUtil.grab8(bb) * K3;
hash ^= MetroHashInternalUtil.rotateRight64(hash, 55) * K1;
}
private void metroHash64_4(final ByteBuffer bb) {
hash += MetroHashInternalUtil.grab4(bb) * K3;
hash ^= MetroHashInternalUtil.rotateRight64(hash, 26) * K1;
}
private void metroHash64_2(final ByteBuffer bb) {
hash += MetroHashInternalUtil.grab2(bb) * K3;
hash ^= MetroHashInternalUtil.rotateRight64(hash, 48) * K1;
}
private void metroHash64_1(final ByteBuffer bb) {
hash += MetroHashInternalUtil.grab1(bb) * K3;
hash ^= MetroHashInternalUtil.rotateRight64(hash, 37) * K1;
}
// endregion
}

View File

@ -0,0 +1,51 @@
package cn.hutool.core.codec.hash.metro;
import java.nio.ByteBuffer;
class MetroHashInternalUtil {
static void writeLittleEndian(final long hash, final ByteBuffer output) {
output.put((byte) hash);
output.put((byte) (hash >>> 8));
output.put((byte) (hash >>> 16));
output.put((byte) (hash >>> 24));
output.put((byte) (hash >>> 32));
output.put((byte) (hash >>> 40));
output.put((byte) (hash >>> 48));
output.put((byte) (hash >>> 56));
}
static long rotateRight64(final long x, final int r) {
return (x >>> r) | (x << (64 - r));
}
static long grab1(final ByteBuffer bb) {
return ((long) bb.get() & 0xFFL);
}
static long grab2(final ByteBuffer bb) {
final long v0 = bb.get();
final long v1 = bb.get();
return (v0 & 0xFFL) | (v1 & 0xFFL) << 8;
}
static long grab4(final ByteBuffer bb) {
final long v0 = bb.get();
final long v1 = bb.get();
final long v2 = bb.get();
final long v3 = bb.get();
return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24;
}
static long grab8(final ByteBuffer bb) {
final long v0 = bb.get();
final long v1 = bb.get();
final long v2 = bb.get();
final long v3 = bb.get();
final long v4 = bb.get();
final long v5 = bb.get();
final long v6 = bb.get();
final long v7 = bb.get();
return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24 | (v4 & 0xFFL) << 32 | (v5 & 0xFFL) << 40 | (v6 & 0xFFL) << 48 | (v7 & 0xFFL) << 56;
}
}

View File

@ -0,0 +1,8 @@
/**
* MetroHash算法实现<br>
* <p>
* 参考https://github.com/postamar/java-metrohash
*
* @author postamar, looly
*/
package cn.hutool.core.codec.hash.metro;

View File

@ -95,6 +95,7 @@ public class LineIter extends ComputeIter<String> implements IterableIter<String
* @param line 需要验证的行
* @return 是否通过验证
*/
@SuppressWarnings("unused")
protected boolean isValidLine(final String line) {
return true;
}

View File

@ -3,13 +3,7 @@ package cn.hutool.core.comparator;
import cn.hutool.core.lang.Chain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.*;
/**
* 比较器链此链包装了多个比较器最终比较结果按照比较器顺序综合多个比较器结果<br>
@ -18,6 +12,7 @@ import java.util.Objects;
*
* @author looly
* @since 3.0.7
* @param <E> 被比较的对象
*/
public class ComparatorChain<E> implements Chain<Comparator<E>, ComparatorChain<E>>, Comparator<E>, Serializable {
private static final long serialVersionUID = -2426725788913962429L;
@ -38,11 +33,11 @@ public class ComparatorChain<E> implements Chain<Comparator<E>, ComparatorChain<
//------------------------------------------------------------------------------------- Static method start
/**
* 构建 {@link ComparatorChain}
* 构建 {@code ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparator 比较器
* @return {@link ComparatorChain}
* @return {@code ComparatorChain}
* @since 5.4.3
*/
public static <E> ComparatorChain<E> of(final Comparator<E> comparator) {
@ -50,12 +45,12 @@ public class ComparatorChain<E> implements Chain<Comparator<E>, ComparatorChain<
}
/**
* 构建 {@link ComparatorChain}
* 构建 {@code ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparator 比较器
* @param reverse 是否反向
* @return {@link ComparatorChain}
* @return {@code ComparatorChain}
* @since 5.4.3
*/
public static <E> ComparatorChain<E> of(final Comparator<E> comparator, final boolean reverse) {
@ -63,11 +58,11 @@ public class ComparatorChain<E> implements Chain<Comparator<E>, ComparatorChain<
}
/**
* 构建 {@link ComparatorChain}
* 构建 {@code ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparators 比较器数组
* @return {@link ComparatorChain}
* @return {@code ComparatorChain}
* @since 5.4.3
*/
@SafeVarargs
@ -76,11 +71,11 @@ public class ComparatorChain<E> implements Chain<Comparator<E>, ComparatorChain<
}
/**
* 构建 {@link ComparatorChain}
* 构建 {@code ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparators 比较器列表
* @return {@link ComparatorChain}
* @return {@code ComparatorChain}
* @since 5.4.3
*/
public static <E> ComparatorChain<E> of(final List<Comparator<E>> comparators) {
@ -88,12 +83,12 @@ public class ComparatorChain<E> implements Chain<Comparator<E>, ComparatorChain<
}
/**
* 构建 {@link ComparatorChain}
* 构建 {@code ComparatorChain}
*
* @param <E> 被比较对象类型
* @param comparators 比较器列表
* @param bits {@link Comparator} 列表对应的排序boolean值true表示正序false反序
* @return {@link ComparatorChain}
* @return {@code ComparatorChain}
* @since 5.4.3
*/
public static <E> ComparatorChain<E> of(final List<Comparator<E>> comparators, final BitSet bits) {

View File

@ -830,6 +830,7 @@ public class Convert {
* @param notConvertSet 不替换的字符集合
* @return 替换后的字符
*/
@SuppressWarnings("UnnecessaryUnicodeEscape")
public static String toDBC(final String text, final Set<Character> notConvertSet) {
if(StrUtil.isBlank(text)) {
return text;

View File

@ -24,6 +24,9 @@ import java.util.List;
public class ArrayConverter extends AbstractConverter {
private static final long serialVersionUID = 1L;
/**
* 单例
*/
public static final ArrayConverter INSTANCE = new ArrayConverter();
/**

View File

@ -3,23 +3,29 @@ package cn.hutool.core.date;
/**
* 季度枚举
*
* @author zhfish(https : / / github.com / zhfish)
* @see #Q1
* @see #Q2
* @see #Q3
* @see #Q4
*
* @author zhfish(https://github.com/zhfish)
*
*/
public enum Quarter {
/** 第一季度 */
/**
* 第一季度
*/
Q1(1),
/** 第二季度 */
/**
* 第二季度
*/
Q2(2),
/** 第三季度 */
/**
* 第三季度
*/
Q3(3),
/** 第四季度 */
/**
* 第四季度
*/
Q4(4);
// ---------------------------------------------------------------
@ -29,6 +35,11 @@ public enum Quarter {
this.value = value;
}
/**
* 获取季度值
*
* @return 季度值
*/
public int getValue() {
return this.value;
}
@ -36,13 +47,12 @@ public enum Quarter {
/**
* 季度int转换为Season枚举对象<br>
*
* @param intValue 季度int表示
* @return {@code Quarter}
* @see #Q1
* @see #Q2
* @see #Q3
* @see #Q4
*
* @param intValue 季度int表示
* @return {@link Quarter}
*/
public static Quarter of(final int intValue) {
switch (intValue) {

View File

@ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit;
* System.currentTimeMillis()的调用比new一个普通对象要耗时的多具体耗时高出多少我还没测试过有人说是100倍左右
* System.currentTimeMillis()之所以慢是因为去跟系统打了一次交道
* 后台定时更新时钟JVM退出时线程自动回收
*
* <p>
* see <a href="http://git.oschina.net/yu120/sequence">http://git.oschina.net/yu120/sequence</a>
* @author lry, looly
*/

View File

@ -573,17 +573,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mValue = value;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return mValue.length();
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
buffer.append(mValue);
@ -610,9 +604,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mValues = values;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
int max = 0;
@ -625,9 +616,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
return max;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
buffer.append(mValues[calendar.get(mField)]);
@ -651,25 +639,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mField = field;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return 4;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(mField));
}
/**
* {@inheritDoc}
*/
@Override
public final void appendTo(final Appendable buffer, final int value) throws IOException {
if (value < 10) {
@ -697,25 +676,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
UnpaddedMonthField() {
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return 2;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
}
/**
* {@inheritDoc}
*/
@Override
public final void appendTo(final Appendable buffer, final int value) throws IOException {
if (value < 10) {
@ -750,25 +720,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mSize = size;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return mSize;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(mField));
}
/**
* {@inheritDoc}
*/
@Override
public final void appendTo(final Appendable buffer, final int value) throws IOException {
appendFullDigits(buffer, value, mSize);
@ -792,25 +753,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mField = field;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return 2;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(mField));
}
/**
* {@inheritDoc}
*/
@Override
public final void appendTo(final Appendable buffer, final int value) throws IOException {
if (value < 100) {
@ -835,25 +787,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
TwoDigitYearField() {
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return 2;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(Calendar.YEAR) % 100);
}
/**
* {@inheritDoc}
*/
@Override
public final void appendTo(final Appendable buffer, final int value) throws IOException {
appendDigits(buffer, value);
@ -874,25 +817,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
TwoDigitMonthField() {
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return 2;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
}
/**
* {@inheritDoc}
*/
@Override
public final void appendTo(final Appendable buffer, final int value) throws IOException {
appendDigits(buffer, value);
@ -916,17 +850,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mRule = rule;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return mRule.estimateLength();
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
int value = calendar.get(Calendar.HOUR);
@ -936,9 +864,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mRule.appendTo(buffer, value);
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final int value) throws IOException {
mRule.appendTo(buffer, value);
@ -962,17 +887,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mRule = rule;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return mRule.estimateLength();
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
int value = calendar.get(Calendar.HOUR_OF_DAY);
@ -982,9 +901,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mRule.appendTo(buffer, value);
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final int value) throws IOException {
mRule.appendTo(buffer, value);
@ -1103,9 +1019,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mDaylight = getTimeZoneDisplay(timeZone, true, style, locale);
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
// We have no access to the Calendar object that will be passed to
@ -1114,9 +1027,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
return Math.max(mStandard.length(), mDaylight.length());
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
final TimeZone zone = calendar.getTimeZone();
@ -1148,17 +1058,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mColon = colon;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return 5;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
@ -1227,17 +1131,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
this.length = length;
}
/**
* {@inheritDoc}
*/
@Override
public int estimateLength() {
return length;
}
/**
* {@inheritDoc}
*/
@Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
@ -1298,17 +1196,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
mLocale = locale;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return (mStyle * 31 + mLocale.hashCode()) * 31 + mTimeZone.hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {

View File

@ -19,6 +19,11 @@ public class AppendableWriter extends Writer implements Appendable {
private final boolean flushable;
private boolean closed;
/**
* 构造
*
* @param appendable {@link Appendable}
*/
public AppendableWriter(final Appendable appendable) {
this.appendable = appendable;
this.flushable = appendable instanceof Flushable;

View File

@ -1,7 +1,5 @@
package cn.hutool.core.io.file.visitor;
import cn.hutool.core.lang.Console;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@ -17,6 +15,9 @@ import java.nio.file.attribute.BasicFileAttributes;
*/
public class DelVisitor extends SimpleFileVisitor<Path> {
/**
* 单例对象
*/
public static DelVisitor INSTANCE = new DelVisitor();
@Override

View File

@ -33,7 +33,7 @@ public class DelayWatcher implements Watcher {
//---------------------------------------------------------------------------------------------------------- Constructor start
/**
* 构造
* @param watcher 实际处理触发事件的监视器{@link Watcher}不可以是{@link DelayWatcher}
* @param watcher 实际处理触发事件的监视器{@link Watcher}不可以是{@code DelayWatcher}
* @param delay 延迟时间单位毫秒
*/
public DelayWatcher(final Watcher watcher, final long delay) {

View File

@ -1,6 +1,5 @@
package cn.hutool.core.io.watch.watchers;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.watch.Watcher;
import cn.hutool.core.lang.Chain;
@ -23,9 +22,9 @@ public class WatcherChain implements Watcher, Chain<Watcher, WatcherChain>{
final private List<Watcher> chain;
/**
* 创建观察者链{@link WatcherChain}
* 创建观察者链{@code WatcherChain}
* @param watchers 观察者列表
* @return {@link WatcherChain}
* @return {@code WatcherChain}
*/
public static WatcherChain of(final Watcher... watchers) {
return new WatcherChain(watchers);

View File

@ -28,11 +28,10 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.func.SerSupplier;
import cn.hutool.core.text.StrUtil;
import java.util.Objects;
import java.util.Optional;
import java.util.Collection;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

View File

@ -39,7 +39,7 @@ public enum AnsiStyle implements AnsiElement {
private final int code;
AnsiStyle(int code) {
AnsiStyle(final int code) {
this.code = code;
}

View File

@ -41,12 +41,12 @@ public interface Bound<T extends Comparable<? super T>> extends Predicate<T>, Co
/**
* 无穷小的描述
*/
String INFINITE_MIN = "-\u221e";
String INFINITE_MIN = "-";
/**
* 无穷大的藐视
*/
String INFINITE_MAX = "+\u221e";
String INFINITE_MAX = "+";
// region --------------- static methods
/**

View File

@ -54,12 +54,13 @@ class NoneLowerBound<T extends Comparable<? super T>> implements Bound<T> {
* <ul>
* <li>-1<em>t1</em><em>t2</em>的左侧</li>
* <li>0<em>t1</em><em>t2</em>的重合</li>
* <li>-1<em>t1</em><em>t2</em>的右侧</li>
* <li>-1<em>t1</em><em>t2</em>的右侧不存在</li>
* </ul>
*
* @param bound 边界
* @return 位置
*/
@SuppressWarnings("ComparatorMethodParameterNotUsed")
@Override
public int compareTo(final Bound<T> bound) {
return bound instanceof NoneLowerBound ? 0 : -1;
@ -102,7 +103,7 @@ class NoneLowerBound<T extends Comparable<? super T>> implements Bound<T> {
*/
@Override
public String toString() {
return "{x | x > -\u221e}";
return "{x | x > -}";
}
}

View File

@ -80,7 +80,7 @@ class NoneUpperBound<T extends Comparable<? super T>> implements Bound<T> {
*/
@Override
public String toString() {
return "{x | x < +\u221e}";
return "{x | x < +}";
}
/**

View File

@ -206,7 +206,7 @@ public class RowKeyTable<R, C, V> extends AbsTable<R, C, V> {
final Collection<Map<C, V>> values = this.raw.values();
final List<C> result = new ArrayList<>(values.size() * 16);
for (final Map<C, V> map : values) {
map.forEach((key, value)->{result.add(key);});
map.forEach((key, value)-> result.add(key));
}
return result;
}

View File

@ -3,7 +3,7 @@ package cn.hutool.core.math;
/**
* 通过位运算表示状态的工具类<br>
* 参数必须是 `偶数` `大于等于0`
*
* <p>
* 工具实现见博客https://blog.starxg.com/2020/11/bit-status/
*
* @author huangxingguangsenssic

View File

@ -121,7 +121,7 @@ public class MethodHandleUtil {
* return "Quack";
* }
* }
*
* <p>
* Duck duck = (Duck) Proxy.newProxyInstance(
* ClassLoaderUtil.getClassLoader(),
* new Class[] { Duck.class },
@ -167,7 +167,7 @@ public class MethodHandleUtil {
* return "Quack";
* }
* }
*
* <p>
* Duck duck = (Duck) Proxy.newProxyInstance(
* ClassLoaderUtil.getClassLoader(),
* new Class[] { Duck.class },
@ -193,7 +193,7 @@ public class MethodHandleUtil {
* return "Quack";
* }
* }
*
* <p>
* Duck duck = (Duck) Proxy.newProxyInstance(
* ClassLoaderUtil.getClassLoader(),
* new Class[] { Duck.class },

View File

@ -893,7 +893,7 @@ public class ReUtil {
/**
* 替换所有正则匹配的文本并使用自定义函数决定如何替换<br>
* replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分然后经过重新处理组装变成新的内容放回原位
*
* <p>
* <pre class="code">
* replaceAll(this.content, "(\\d+)", parameters -&gt; "-" + parameters.group(1) + "-")
* // 结果为"ZZZaaabbbccc中文-1234-"
@ -912,7 +912,7 @@ public class ReUtil {
/**
* 替换所有正则匹配的文本并使用自定义函数决定如何替换<br>
* replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分然后经过重新处理组装变成新的内容放回原位
*
* <p>
* <pre class="code">
* replaceAll(this.content, "(\\d+)", parameters -&gt; "-" + parameters.group(1) + "-")
* // 结果为"ZZZaaabbbccc中文-1234-"

View File

@ -513,6 +513,13 @@ public class AntPathMatcher {
return builder.toString();
}
/**
* 提取参数
*
* @param pattern 模式
* @param path 路径
* @return 参数
*/
public Map<String, String> extractUriTemplateVariables(final String pattern, final String path) {
final Map<String, String> variables = new LinkedHashMap<>();
final boolean result = doMatch(pattern, path, true, variables);

View File

@ -12,6 +12,7 @@ import cn.hutool.core.text.replacer.LookupReplacer;
public class Html4Escape extends XmlEscape {
private static final long serialVersionUID = 1L;
@SuppressWarnings("UnnecessaryUnicodeEscape")
protected static final String[][] ISO8859_1_ESCAPE = { //
{ "\u00A0", "&nbsp;" }, // non-breaking space
{ "\u00A1", "&iexcl;" }, // inverted exclamation mark
@ -111,6 +112,7 @@ public class Html4Escape extends XmlEscape {
{ "\u00FF", "&yuml;" }, // <EFBFBD> - lowercase y, umlaut
};
@SuppressWarnings("UnnecessaryUnicodeEscape")
protected static final String[][] HTML40_EXTENDED_ESCAPE = {
// <!-- Latin Extended-B -->
{ "\u0192", "&fnof;" }, // latin small f with hook = function= florin, U+0192 ISOtech -->
@ -308,6 +310,9 @@ public class Html4Escape extends XmlEscape {
{ "\u20AC", "&euro;" }, // -- euro sign, U+20AC NEW -->
};
/**
* 构造
*/
public Html4Escape() {
super();
addChain(new LookupReplacer(ISO8859_1_ESCAPE));

View File

@ -9,7 +9,7 @@ import java.util.function.Consumer;
* 当任务队列过长时处于阻塞状态直到添加到队列中
* 如果阻塞过程中被中断就会抛出{@link InterruptedException}异常<br>
* 有时候在线程池内访问第三方接口只希望固定并发数去访问并且不希望丢弃任务时使用此策略队列满的时候会处于阻塞状态(例如刷库的场景)
*
* <p>
* 其他系统内置的拒绝策略见hutool定义的枚举 {@link RejectPolicy} 线程拒绝策略枚举.
*
* @author luozongle

View File

@ -1,7 +1,6 @@
package cn.hutool.core.util;
import cn.hutool.core.collection.SetUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.StrUtil;
import java.util.Set;

View File

@ -298,12 +298,12 @@ public class ByteUtil {
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
for (int i = (Long.BYTES - 1); i >= 0; i--) {
values <<= Byte.SIZE;
values |= (bytes[i + start] & 0xff);
values |= (bytes[i + start] & 0xffL);
}
} else {
for (int i = 0; i < Long.BYTES; i++) {
values <<= Byte.SIZE;
values |= (bytes[i + start] & 0xff);
values |= (bytes[i + start] & 0xffL);
}
}

View File

@ -0,0 +1,119 @@
package cn.hutool.core.codec.hash.metro;
import cn.hutool.core.codec.HexUtil;
import cn.hutool.core.text.StrUtil;
import org.junit.Assert;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class MetroHash128Test {
@Test
public void testEmpty() {
Assert.assertEquals("5F3CA3D41D1CB4606B14684C65FB6", h128(""));
}
@Test
public void test1Low() {
Assert.assertEquals("E84D9EA70174C3184AC6E55552310F85", h128("a"));
}
@Test
public void test1High() {
Assert.assertEquals("9A5BCED4C3CA98CADE13388E3C14C215", h128("é"));
}
@Test
public void test2Palindrome() {
Assert.assertEquals("3DDDF558587273E1FD034EC7CC917AC8", h128("aa"));
}
@Test
public void test2() {
Assert.assertEquals("458E6A18B65C38AD2552335402A068A2", h128("ab"));
}
@Test
public void test3PalindromeLow() {
Assert.assertEquals("19725A6E67A8DD1A84E3C844A20DA938", h128("aaa"));
}
@Test
public void test3PalindromeHigh() {
Assert.assertEquals("1DD9CC1D29B5080D5F9F171FB2C50CBB", h128("ééé"));
}
@Test
public void test3() {
Assert.assertEquals("89AB9CDB9FAF7BA71CD86385C1F801A5", h128("abc"));
}
@Test
public void test4Palindrome() {
Assert.assertEquals("AFD0BBB3764CA0539E46B914B8CB8911", h128("poop"));
}
@Test
public void test4() {
Assert.assertEquals("D11B6DB94FE20E3884F3829AD6613D19", h128("fart"));
}
@Test
public void test5() {
Assert.assertEquals("D45A3A74885F9C842081929D2E9A3A3B", h128("Hello"));
}
@Test
public void test12() {
Assert.assertEquals("A7CEC59B03A9053BA6009EEEC81E81F5", h128("Hello World!"));
}
@Test
public void test31() {
Assert.assertEquals("980CA7496A1B26D24E529DFB2B3A870",
h128("The Quick Brown Fox Jumped Over"));
}
@Test
public void test32() {
Assert.assertEquals("76663CEA442E22F86A6CB41FBA896B9B",
h128("The Quick Brown Fox Jumped Over "));
}
@Test
public void testLonger() {
Assert.assertEquals("7010B2D7C8A3515AE3CA4DBBD9ED30D0",
h128("The Quick Brown Fox Jumped Over The Lazy Dog"));
}
static final byte[] ENDIAN =
StrUtil.utf8Bytes("012345678901234567890123456789012345678901234567890123456789012");
@Test
public void testLittleEndian() {
final ByteBuffer output = ByteBuffer.allocate(16);
MetroHash128.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.LITTLE_ENDIAN);
Assert.assertEquals("C77CE2BFA4ED9F9B0548B2AC5074A297", hex(output.array()));
}
@Test
public void testBigEndian() {
final ByteBuffer output = ByteBuffer.allocate(16);
MetroHash128.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.BIG_ENDIAN);
Assert.assertEquals("97A27450ACB248059B9FEDA4BFE27CC7", hex(output.array()));
}
static String h128(final String input) {
final MetroHash128 mh = MetroHash128.of(0).apply(ByteBuffer.wrap(StrUtil.utf8Bytes(input)));
return hex(mh.getHigh()) + hex(mh.getLow());
}
private static String hex(final long value){
return HexUtil.toHex(value).toUpperCase();
}
private static String hex(final byte[] bytes){
return HexUtil.encodeHexStr(bytes).toUpperCase();
}
}

View File

@ -0,0 +1,118 @@
package cn.hutool.core.codec.hash.metro;
import cn.hutool.core.codec.HexUtil;
import cn.hutool.core.text.StrUtil;
import org.junit.Assert;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* 来自https://github.com/postamar/java-metrohash/blob/master/src/test/java/util/hash/MetroHashTest64.java
*/
public class MetroHash64Test {
@Test
public void testEmpty() {
Assert.assertEquals("705FB008071E967D", h64(""));
}
@Test
public void test1Low() {
Assert.assertEquals("AF6F242B7ED32BCB", h64("a"));
}
@Test
public void test1High() {
Assert.assertEquals("D51BA21D219C37B3", h64("é"));
}
@Test
public void test2Palindrome() {
Assert.assertEquals("3CF3A8F204CAE1B6", h64("aa"));
}
@Test
public void test2() {
Assert.assertEquals("CD2EA2738FC27D98", h64("ab"));
}
@Test
public void test3PalindromeLow() {
Assert.assertEquals("E59031D8D046D241", h64("aaa"));
}
@Test
public void test3PalindromeHigh() {
Assert.assertEquals("FE8325DC6F40511D", h64("ééé"));
}
@Test
public void test3() {
Assert.assertEquals("ED4F5524E6FAFFBB", h64("abc"));
}
@Test
public void test4Palindrome() {
Assert.assertEquals("CD77F739885CCB2C", h64("poop"));
}
@Test
public void test4() {
Assert.assertEquals("B642DCB026D9573C", h64("fart"));
}
@Test
public void test5() {
Assert.assertEquals("A611009FEE6AF8B", h64("Hello"));
}
@Test
public void test12() {
Assert.assertEquals("14BCB49B74E3B404", h64("Hello World!"));
}
@Test
public void test31() {
Assert.assertEquals("D27A7BFACC320E2F",
h64("The Quick Brown Fox Jumped Over"));
}
@Test
public void test32() {
Assert.assertEquals("C313A3A811EAB43B",
h64("The Quick Brown Fox Jumped Over "));
}
@Test
public void testLonger() {
Assert.assertEquals("C7047C2FCA234C05",
h64("The Quick Brown Fox Jumped Over The Lazy Dog"));
}
static final byte[] ENDIAN =
StrUtil.utf8Bytes("012345678901234567890123456789012345678901234567890123456789012");
@Test
public void testLittleEndian() {
final ByteBuffer output = ByteBuffer.allocate(8);
MetroHash64.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.LITTLE_ENDIAN);
Assert.assertEquals("6B753DAE06704BAD", hex(output.array()));
}
@Test
public void testBigEndian() {
final ByteBuffer output = ByteBuffer.allocate(8);
MetroHash64.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.BIG_ENDIAN);
Assert.assertEquals("AD4B7006AE3D756B", hex(output.array()));
}
private String h64(final String value) {
return HexUtil.toHex(MetroHash64.of(0).hash64(StrUtil.utf8Bytes(value))).toUpperCase();
}
private static String hex(final byte[] bytes){
return HexUtil.encodeHexStr(bytes).toUpperCase();
}
}

View File

@ -1,10 +1,11 @@
package cn.hutool.core.codec.hash;
package cn.hutool.core.codec.hash.metro;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.codec.HexUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.codec.hash.CityHash;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.RandomUtil;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@ -16,22 +17,32 @@ public class MetroHashTest {
@Test
public void testEmpty() {
Assert.assertEquals("31290877cceaea29", HexUtil.toHex(MetroHash.INSTANCE.hash64(StrUtil.utf8Bytes(""), 0)));
Assert.assertEquals("705fb008071e967d", HexUtil.toHex(MetroHash64.of(0).hash64(StrUtil.utf8Bytes(""))));
}
@Test
public void test1Low() {
Assert.assertEquals("AF6F242B7ED32BCB", h64("a"));
}
@Test
public void test1High() {
Assert.assertEquals("D51BA21D219C37B3", h64("é"));
}
@Test
public void metroHash64Test() {
final byte[] str = "我是一段测试123".getBytes(CharsetUtil.UTF_8);
final long hash64 = MetroHash.INSTANCE.hash64(str);
Assert.assertEquals(62920234463891865L, hash64);
final long hash64 = MetroHash64.of(0).hash64(str);
Assert.assertEquals(147395857347476456L, hash64);
}
@Test
public void metroHash128Test() {
final byte[] str = "我是一段测试123".getBytes(CharsetUtil.UTF_8);
final long[] hash128 = MetroHash.INSTANCE.hash128(str).getLongArray();
Assert.assertEquals(4956592424592439349L, hash128[0]);
Assert.assertEquals(6301214698325086246L, hash128[1]);
final long[] hash128 = MetroHash128.of(0).hash128(str).getLongArray();
Assert.assertEquals(228255164667538345L, hash128[0]);
Assert.assertEquals(-6394585948993412256L, hash128[1]);
}
/**
@ -49,7 +60,7 @@ public class MetroHashTest {
final long startMetro = System.currentTimeMillis();
for (final String s : strArray) {
MetroHash.INSTANCE.hash64(StrUtil.utf8Bytes(s));
MetroHash64.of(0).hash64(StrUtil.utf8Bytes(s));
}
final long endMetro = System.currentTimeMillis();
@ -73,7 +84,7 @@ public class MetroHashTest {
final long startMetro = System.currentTimeMillis();
for (final String s : strArray) {
MetroHash.INSTANCE.hash128(StrUtil.utf8Bytes(s));
MetroHash128.of(0).hash128(StrUtil.utf8Bytes(s));
}
final long endMetro = System.currentTimeMillis();
@ -90,4 +101,8 @@ public class MetroHashTest {
}
return result;
}
private String h64(final String value) {
return HexUtil.toHex(MetroHash64.of(0).hash64(StrUtil.utf8Bytes(value))).toUpperCase();
}
}

View File

@ -7,13 +7,7 @@ import lombok.Data;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* {@link IterUtil} 单元测试

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.ListUtil;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

View File

@ -11,17 +11,7 @@ import cn.hutool.core.util.RandomUtil;
import org.junit.Assert;
import org.junit.Test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.io.*;
import java.util.List;
public class IoUtilTest {

View File

@ -1,6 +1,5 @@
package cn.hutool.core.builder;
package cn.hutool.core.lang.builder;
import cn.hutool.core.lang.builder.GenericBuilder;
import cn.hutool.core.text.StrUtil;
import lombok.Getter;
import lombok.Setter;

View File

@ -39,13 +39,13 @@ public class BoundTest {
// getValue
Assert.assertNull(bound.getValue());
// toString
Assert.assertEquals("(" + "-\u221e", bound.descBound());
Assert.assertEquals("(" + "-", bound.descBound());
// compareTo
Assert.assertEquals(0, bound.compareTo(bound));
Assert.assertEquals(-1, bound.compareTo(Bound.atMost(1)));
Assert.assertEquals(BoundedRange.all(), bound.toRange());
Assert.assertEquals("{x | x > -\u221e}", bound.toString());
Assert.assertEquals("{x | x > -}", bound.toString());
}
@Test
@ -60,13 +60,13 @@ public class BoundTest {
// getValue
Assert.assertNull(bound.getValue());
// toString
Assert.assertEquals("+\u221e" + ")", bound.descBound());
Assert.assertEquals("+" + ")", bound.descBound());
// compareTo
Assert.assertEquals(0, bound.compareTo(bound));
Assert.assertEquals(1, bound.compareTo(Bound.atMost(1)));
Assert.assertEquals(BoundedRange.all(), bound.toRange());
Assert.assertEquals("{x | x < +\u221e}", bound.toString());
Assert.assertEquals("{x | x < +}", bound.toString());
}
@Test

View File

@ -1,6 +1,5 @@
package cn.hutool.core.reflect;
import cn.hutool.core.reflect.ActualTypeMapperPool;
import org.junit.Assert;
import org.junit.Test;
@ -9,7 +8,7 @@ import java.util.Map;
/**
* <a href="https://gitee.com/dromara/hutool/pulls/447/files">https://gitee.com/dromara/hutool/pulls/447/files</a>
*
* <p>
* TODO 同时继承泛型和实现泛型接口需要解析此处为F
*/
public class ActualTypeMapperPoolTest {

View File

@ -591,9 +591,7 @@ public class AbstractEnhancedWrappedStreamTest {
public void testMapMulti() {
Assert.assertEquals(
asList(1, 2, 3),
wrap(1, 2, 3).mapMulti((t, builder) -> {
builder.accept(t);
}).toList()
wrap(1, 2, 3).mapMulti((t, builder) -> builder.accept(t)).toList()
);
}

View File

@ -59,6 +59,7 @@ public class CharSequenceUtilTest {
Assert.assertEquals("/", result);
}
@SuppressWarnings("UnnecessaryUnicodeEscape")
@Test
public void normalizeTest() {
// https://blog.csdn.net/oscar999/article/details/105326270
@ -155,6 +156,7 @@ public class CharSequenceUtilTest {
Assert.assertNull(CharSequenceUtil.removeSuffixIgnoreCase(null, "ABCdef"));
}
@SuppressWarnings("ConstantValue")
@Test
public void trimToNullTest(){
String a = " ";

View File

@ -8,7 +8,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class issueI5Q4HDTest {
public class IssueI5Q4HDTest {
@Test
public void matchAllTest(){

View File

@ -27,6 +27,7 @@ public class CharUtilTest {
Assert.assertTrue(CharUtil.isChar(a));
}
@SuppressWarnings("UnnecessaryUnicodeEscape")
@Test
public void isBlankCharTest(){
final char a = '\u00A0';
@ -56,6 +57,7 @@ public class CharUtilTest {
Assert.assertEquals('⑳', CharUtil.toCloseByNumber(20));
}
@SuppressWarnings("UnnecessaryUnicodeEscape")
@Test
public void issueI5UGSQTest(){
char c = '\u3164';

View File

@ -9,6 +9,9 @@ import cn.hutool.core.text.StrUtil;
*/
public class AlwaysTrueMatcher implements PartMatcher {
/**
* 单例
*/
public static AlwaysTrueMatcher INSTANCE = new AlwaysTrueMatcher();
@Override

View File

@ -18,7 +18,7 @@ import cn.hutool.crypto.symmetric.PBKDF2;
import cn.hutool.crypto.symmetric.RC4;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.crypto.symmetric.ZUC;
import cn.hutool.crypto.symmetric.fpe.FPE;
import cn.hutool.crypto.symmetric.FPE;
import org.bouncycastle.crypto.AlphabetMapper;
import javax.crypto.Cipher;

View File

@ -116,7 +116,7 @@ public class Sign extends BaseAsymmetric<Sign> {
/**
* 构造
*
* <p>
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
* 私钥和公钥可以单独传入一个如此则只能使用此钥匙来做签名或验证
*
@ -144,7 +144,7 @@ public class Sign extends BaseAsymmetric<Sign> {
/**
* 构造
*
* <p>
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
* 私钥和公钥可以单独传入一个如此则只能使用此钥匙来做签名或验证
*

View File

@ -1,8 +1,7 @@
package cn.hutool.crypto.symmetric.fpe;
package cn.hutool.crypto.symmetric;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import org.bouncycastle.crypto.AlphabetMapper;
import org.bouncycastle.jcajce.spec.FPEParameterSpec;
@ -24,7 +23,7 @@ import java.io.Serializable;
* <li>数据类型不变加密前是数字类型加密后仍然是数字类型</li>
* <li>加密过程可逆加密后的数据可以通过密钥解密还原原始数据</li>
* </ul>
*
* <p>
* 此类基于BouncyCastle实现
*
* @author looly

View File

@ -1,6 +1,7 @@
package cn.hutool.crypto.symmetric.fpe;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.symmetric.FPE;
import org.bouncycastle.crypto.util.BasicAlphabetMapper;
import org.junit.Assert;
import org.junit.Test;

View File

@ -1,23 +1,10 @@
package cn.hutool.db;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.func.SerFunction;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.handler.BeanListHandler;
import cn.hutool.db.handler.EntityHandler;
import cn.hutool.db.handler.EntityListHandler;
import cn.hutool.db.handler.NumberHandler;
import cn.hutool.db.handler.ResultSetUtil;
import cn.hutool.db.handler.RsHandler;
import cn.hutool.db.handler.StringHandler;
import cn.hutool.db.sql.Condition;
import cn.hutool.db.handler.*;
import cn.hutool.db.sql.*;
import cn.hutool.db.sql.Condition.LikeType;
import cn.hutool.db.sql.LogicalOperator;
import cn.hutool.db.sql.Query;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.SqlExecutor;
import cn.hutool.db.sql.SqlUtil;
import cn.hutool.db.sql.QuoteWrapper;
import javax.sql.DataSource;
import java.io.Serializable;

View File

@ -29,7 +29,7 @@ public class PooledDataSource extends AbstractDataSource {
* 获得一个数据源
*
* @param group 数据源分组
* @return {@link PooledDataSource}
* @return {@code PooledDataSource}
*/
synchronized public static PooledDataSource getDataSource(final String group) {
return new PooledDataSource(group);
@ -38,7 +38,7 @@ public class PooledDataSource extends AbstractDataSource {
/**
* 获得一个数据源使用空分组
*
* @return {@link PooledDataSource}
* @return {@code PooledDataSource}
*/
synchronized public static PooledDataSource getDataSource() {
return new PooledDataSource();

View File

@ -7,7 +7,7 @@ import java.sql.SQLException;
/**
* 结果集处理接口<br>
* 此接口用于实现{@link ResultSet} 转换或映射为用户指定的pojo对象
*
* <p>
* 默认实现有
* @see EntityHandler
* @see EntityListHandler

View File

@ -10,64 +10,177 @@ import java.util.Map;
* @see java.sql.Types
*/
public enum JdbcType {
ARRAY(java.sql.Types.ARRAY), //
BIT(java.sql.Types.BIT), //
TINYINT(java.sql.Types.TINYINT), //
SMALLINT(java.sql.Types.SMALLINT), //
INTEGER(java.sql.Types.INTEGER), //
BIGINT(java.sql.Types.BIGINT), //
FLOAT(java.sql.Types.FLOAT), //
REAL(java.sql.Types.REAL), //
DOUBLE(java.sql.Types.DOUBLE), //
NUMERIC(java.sql.Types.NUMERIC), //
DECIMAL(java.sql.Types.DECIMAL), //
CHAR(java.sql.Types.CHAR), //
VARCHAR(java.sql.Types.VARCHAR), //
LONGVARCHAR(java.sql.Types.LONGVARCHAR), //
DATE(java.sql.Types.DATE), //
TIME(java.sql.Types.TIME), //
TIMESTAMP(java.sql.Types.TIMESTAMP), //
BINARY(java.sql.Types.BINARY), //
VARBINARY(java.sql.Types.VARBINARY), //
LONGVARBINARY(java.sql.Types.LONGVARBINARY), //
NULL(java.sql.Types.NULL), //
OTHER(java.sql.Types.OTHER), //
BLOB(java.sql.Types.BLOB), //
CLOB(java.sql.Types.CLOB), //
BOOLEAN(java.sql.Types.BOOLEAN), //
CURSOR(-10), // Oracle
UNDEFINED(Integer.MIN_VALUE + 1000), //
NVARCHAR(java.sql.Types.NVARCHAR), // JDK6
NCHAR(java.sql.Types.NCHAR), // JDK6
NCLOB(java.sql.Types.NCLOB), // JDK6
STRUCT(java.sql.Types.STRUCT), //
JAVA_OBJECT(java.sql.Types.JAVA_OBJECT), //
DISTINCT(java.sql.Types.DISTINCT), //
REF(java.sql.Types.REF), //
DATALINK(java.sql.Types.DATALINK), //
ROWID(java.sql.Types.ROWID), // JDK6
LONGNVARCHAR(java.sql.Types.LONGNVARCHAR), // JDK6
SQLXML(java.sql.Types.SQLXML), // JDK6
DATETIMEOFFSET(-155), // SQL Server 2008
TIME_WITH_TIMEZONE(2013), // JDBC 4.2 JDK8
TIMESTAMP_WITH_TIMEZONE(2014); // JDBC 4.2 JDK8
public final int typeCode;
/**
* 构造
*
* @param code {@link java.sql.Types} 中对应的值
* {@link java.sql.Types#ARRAY}
*/
JdbcType(final int code) {
this.typeCode = code;
}
ARRAY(java.sql.Types.ARRAY), //
/**
* {@link java.sql.Types#BIT}
*/
BIT(java.sql.Types.BIT), //
/**
* {@link java.sql.Types#TINYINT}
*/
TINYINT(java.sql.Types.TINYINT), //
/**
* {@link java.sql.Types#SMALLINT}
*/
SMALLINT(java.sql.Types.SMALLINT), //
/**
* {@link java.sql.Types#INTEGER}
*/
INTEGER(java.sql.Types.INTEGER), //
/**
* {@link java.sql.Types#BIGINT}
*/
BIGINT(java.sql.Types.BIGINT), //
/**
* {@link java.sql.Types#FLOAT}
*/
FLOAT(java.sql.Types.FLOAT), //
/**
* {@link java.sql.Types#REAL}
*/
REAL(java.sql.Types.REAL), //
/**
* {@link java.sql.Types#DOUBLE}
*/
DOUBLE(java.sql.Types.DOUBLE), //
/**
* {@link java.sql.Types#NUMERIC}
*/
NUMERIC(java.sql.Types.NUMERIC), //
/**
* {@link java.sql.Types#DECIMAL}
*/
DECIMAL(java.sql.Types.DECIMAL), //
/**
* {@link java.sql.Types#CHAR}
*/
CHAR(java.sql.Types.CHAR), //
/**
* {@link java.sql.Types#VARCHAR}
*/
VARCHAR(java.sql.Types.VARCHAR), //
/**
* {@link java.sql.Types#LONGVARCHAR}
*/
LONGVARCHAR(java.sql.Types.LONGVARCHAR), //
/**
* {@link java.sql.Types#DATE}
*/
DATE(java.sql.Types.DATE), //
/**
* {@link java.sql.Types#TIME}
*/
TIME(java.sql.Types.TIME), //
/**
* {@link java.sql.Types#TIMESTAMP}
*/
TIMESTAMP(java.sql.Types.TIMESTAMP), //
/**
* {@link java.sql.Types#BINARY}
*/
BINARY(java.sql.Types.BINARY), //
/**
* {@link java.sql.Types#VARBINARY}
*/
VARBINARY(java.sql.Types.VARBINARY), //
/**
* {@link java.sql.Types#LONGVARBINARY}
*/
LONGVARBINARY(java.sql.Types.LONGVARBINARY), //
/**
* {@link java.sql.Types#NULL}
*/
NULL(java.sql.Types.NULL), //
/**
* {@link java.sql.Types#OTHER}
*/
OTHER(java.sql.Types.OTHER), //
/**
* {@link java.sql.Types#BLOB}
*/
BLOB(java.sql.Types.BLOB), //
/**
* {@link java.sql.Types#CLOB}
*/
CLOB(java.sql.Types.CLOB), //
/**
* {@link java.sql.Types#BOOLEAN}
*/
BOOLEAN(java.sql.Types.BOOLEAN), //
/**
* Oracle Cursor
*/
CURSOR(-10), // Oracle
/**
* UNDEFINED
*/
UNDEFINED(Integer.MIN_VALUE + 1000), //
/**
* {@link java.sql.Types#NVARCHAR}
*/
NVARCHAR(java.sql.Types.NVARCHAR), // JDK6
/**
* {@link java.sql.Types#NCHAR}
*/
NCHAR(java.sql.Types.NCHAR), // JDK6
/**
* {@link java.sql.Types#NCLOB}
*/
NCLOB(java.sql.Types.NCLOB), // JDK6
/**
* {@link java.sql.Types#STRUCT}
*/
STRUCT(java.sql.Types.STRUCT),
/**
* {@link java.sql.Types#JAVA_OBJECT}
*/
JAVA_OBJECT(java.sql.Types.JAVA_OBJECT),
/**
* {@link java.sql.Types#DISTINCT}
*/
DISTINCT(java.sql.Types.DISTINCT),
/**
* {@link java.sql.Types#REF}
*/
REF(java.sql.Types.REF),
/**
* {@link java.sql.Types#BOOLEAN}
*/
DATALINK(java.sql.Types.DATALINK), //
/**
* {@link java.sql.Types#ROWID}
*/
ROWID(java.sql.Types.ROWID), // JDK6
/**
* {@link java.sql.Types#LONGNVARCHAR}
*/
LONGNVARCHAR(java.sql.Types.LONGNVARCHAR), // JDK6
/**
* {@link java.sql.Types#SQLXML}
*/
SQLXML(java.sql.Types.SQLXML), // JDK6
/**
* SQL Server 2008 DateTimeOffset
*/
DATETIMEOFFSET(-155), // SQL Server 2008
/**
* Time With TimeZone
*/
TIME_WITH_TIMEZONE(2013), // JDBC 4.2 JDK8
/**
* TimeStamp With TimeZone
*/
TIMESTAMP_WITH_TIMEZONE(2014); // JDBC 4.2 JDK8
// 此处无写操作使用HashMap没有线程安全问题
private static final Map<Integer, JdbcType> CODE_MAP = new HashMap<>(128, 1);
static {
for (final JdbcType type : JdbcType.values()) {
CODE_MAP.put(type.typeCode, type);
CODE_MAP.put(type.value, type);
}
}
@ -81,4 +194,23 @@ public enum JdbcType {
return CODE_MAP.get(code);
}
private final int value;
/**
* 构造
*
* @param code {@link java.sql.Types} 中对应的值
*/
JdbcType(final int code) {
this.value = code;
}
/**
* 获取枚举值即JDBC字段类型代码
*
* @return 字段类型代码
*/
public int getValue() {
return this.value;
}
}

View File

@ -67,97 +67,215 @@ public class ResultColumn {
}
}
/**
* 是否自增
*
* @return 是否自增
*/
public boolean isAutoIncrement() {
return autoIncrement;
}
/**
* 是否大小写敏感
*
* @return 是否大小写敏感
*/
public boolean isCaseSensitive() {
return caseSensitive;
}
/**
* 是否可搜索
*
* @return 是否可搜索
*/
public boolean isSearchable() {
return searchable;
}
/**
* 是否为货币
*
* @return 是否为货币
*/
public boolean isCurrency() {
return currency;
}
/**
* 获取null值选项即是否可以为{@code null}
*
* @return null值选项是否可以为{@code null}
*/
public int getNullable() {
return nullable;
}
/**
* 获取列null值选项枚举即是否可以为{@code null}
*
* @return 列null值选项枚举即是否可以为{@code null}
*/
public ColumnNullable getNullableEnum() {
return ColumnNullable.of(getNullable());
}
/**
* 是否为带正负号的数字
*
* @return 是否为带正负号的数字
*/
public boolean isSigned() {
return signed;
}
/**
* 获取正常最大宽度以字符数计
*
* @return 正常最大宽度
*/
public int getDisplaySize() {
return displaySize;
}
/**
* 获取列标签
*
* @return 标签
*/
public String getLabel() {
return label;
}
/**
* 获取列名称
*
* @return 列名称
*/
public String getName() {
return name;
}
/**
* 获取表架构名称
*
* @return 表架构名称
*/
public String getSchemaName() {
return schemaName;
}
/**
* 获取小数位数
*
* @return 小数位数
*/
public int getPrecision() {
return precision;
}
/**
* 小数点右侧的位数
*
* @return 小数点右侧的位数
*/
public int getScale() {
return scale;
}
/**
* 获取表名
*
* @return 表名
*/
public String getTableName() {
return tableName;
}
/**
* 获取表的目录名称
*
* @return 表的目录名称
*/
public String getCatalogName() {
return catalogName;
}
/**
* 获取SQL类型
*
* @return SQL类型
*/
public int getType() {
return type;
}
/**
* 获取类型名称
*
* @return 类型名称
*/
public String getTypeName() {
return typeName;
}
/**
* 是否只读不可写入
*
* @return 是否只读不可写入
*/
public boolean isReadOnly() {
return readOnly;
}
/**
* 是否能够成功在指定列上写入
*
* @return 是否能够成功在指定列上写入
*/
public boolean isWritable() {
return writable;
}
/**
* 写入操作是否将一定成功
*
* @return 写入操作是否将一定成功
*/
public boolean isDefinitelyWritable() {
return definitelyWritable;
}
/**
* 如果调用getObject方法来从列中检索值则返回生成其实例的 Java 类的完全限定名称
*
* @return 包含类的完全限定名称
*/
public String getClassName() {
return className;
}
/**
* 列null值选项
*/
public enum ColumnNullable {
/**
* 列不允许有null
*/
NO_NULLS(ResultSetMetaData.columnNoNulls),
/**
* 列允许有null
*/
NULLABLE(ResultSetMetaData.columnNullable),
/**
* 未知
*/
UNKNOWN(ResultSetMetaData.columnNullableUnknown);
/**
* ResultSetMetaData中的int值转枚举
*
* @param nullable nullable值
* @return ColumnNullable
*/
@ -173,8 +291,18 @@ public class ResultColumn {
}
final int value;
ColumnNullable(final int value) {
this.value = value;
}
/**
* 获取枚举值即列null值选项代码
*
* @return 列null值选项代码
*/
public int getValue() {
return this.value;
}
}
}

View File

@ -47,7 +47,7 @@ public final class ProxyUtil {
* 3调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象并且用interfaces参数遍历其所有接口的方法这些实现方法的实现本质上是通过反射调用被代理对象的方法<br>
* 4将$Proxy0的实例返回给客户端 <br>
* 5当调用代理类的相应方法时相当于调用 {@link InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])} 方法
*
* <p> <p>
*
* @param <T> 被代理对象类型
* @param classloader 被代理类对应的ClassLoader

View File

@ -305,7 +305,7 @@ public class JavaInfo implements Serializable {
*
* <p>
* 例如
*
* <p>
*
* <ul>
* <li>测试JDK 1.2{@code isJavaVersionAtLeast(1.2f)}</li>
@ -324,7 +324,7 @@ public class JavaInfo implements Serializable {
*
* <p>
* 例如
*
* <p>
*
* <ul>
* <li>测试JDK 1.2{@code isJavaVersionAtLeast(120)}</li>

View File

@ -25,6 +25,7 @@ public class QrAsciiArt {
this.qrConfig = qrConfig;
}
@SuppressWarnings("UnnecessaryUnicodeEscape")
@Override
public String toString() {
final int width = matrix.getWidth();

View File

@ -23,13 +23,9 @@ import org.apache.http.message.BasicHeader;
import java.io.IOException;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Apache HttpClient5的HTTP请求引擎

View File

@ -2,7 +2,6 @@ package cn.hutool.http.client.engine.httpclient5;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.net.ssl.SSLUtil;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.http.GlobalHeaders;
import cn.hutool.http.HttpException;

View File

@ -1,7 +1,5 @@
package cn.hutool.http.ssl;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.net.ssl.SSLUtil;
import cn.hutool.core.util.ArrayUtil;
import javax.net.ssl.SSLSocket;

View File

@ -7,7 +7,7 @@ import org.junit.Test;
/**
* ContentType 单元测试
*
* <p>
*
*/
public class ContentTypeTest {

View File

@ -1,9 +1,8 @@
package cn.hutool.http.body;
package cn.hutool.http.client.body;
import cn.hutool.core.io.resource.HttpResource;
import cn.hutool.core.io.resource.StringResource;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.io.resource.HttpResource;
import cn.hutool.http.client.body.MultipartBody;
import org.junit.Assert;
import org.junit.Test;

View File

@ -460,6 +460,7 @@ public final class InternalJSONUtil {
* @param c 字符
* @return 转义后的字符串
*/
@SuppressWarnings("UnnecessaryUnicodeEscape")
private static String escape(final char c) {
switch (c) {
case '\b':

View File

@ -10,7 +10,7 @@ import org.junit.Test;
* 测试在bean转换时使用BeanConverter默认忽略转换失败的字段
* 现阶段Converter的问题在于无法更细粒度的控制转换失败的范围例如Bean的一个字段为List
* list任意一个item转换失败都会导致这个list为null
*
* <p>
* TODO 需要在Converter中添加ConvertOption用于更细粒度的控制转换规则
*/
public class Issue1200Test {

View File

@ -9,7 +9,7 @@ import java.time.LocalDateTime;
/**
* https://gitee.com/loolly/dashboard/issues?id=I1F8M2
*/
public class IssueI1F8M2 {
public class IssueI1F8M2Test {
@Test
public void toBeanTest() {
final String jsonStr = "{\"eventType\":\"fee\",\"fwdAlertingTime\":\"2020-04-22 16:34:13\",\"fwdAnswerTime\":\"\"}";

View File

@ -11,7 +11,7 @@ import java.util.List;
* 此问题原来出在BeanCopier中判断循环引用使用了equals并不严谨
* 修复后使用==判断循环引用
*/
public class IssueI1H2VN {
public class IssueI1H2VNTest {
@Test
public void toBeanTest() {

View File

@ -10,7 +10,7 @@ import java.time.LocalDateTime;
/**
* 测试带毫秒的日期转换
*/
public class IssueI3BS4S {
public class IssueI3BS4STest {
@Test
public void toBeanTest(){

View File

@ -5,7 +5,7 @@ import lombok.Data;
import org.junit.Assert;
import org.junit.Test;
public class IssueI3EGJP {
public class IssueI3EGJPTest {
@Test
public void hutoolMapToBean() {

View File

@ -2,7 +2,6 @@ package cn.hutool.json;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.json.serialize.JSONStringer;
@ -14,11 +13,7 @@ import org.junit.Assert;
import org.junit.Test;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.*;
public class JSONUtilTest {

View File

@ -12,9 +12,8 @@ public class GlobalValueWriterMappingTest {
@Before
public void init(){
GlobalValueWriterMapping.put(CustomSubBean.class, (JSONValueWriter<CustomSubBean>) (writer, value) -> {
writer.writeRaw(String.valueOf(value.getId()));
});
GlobalValueWriterMapping.put(CustomSubBean.class,
(JSONValueWriter<CustomSubBean>) (writer, value) -> writer.writeRaw(String.valueOf(value.getId())));
}
@Test

View File

@ -9,8 +9,8 @@ import cn.hutool.log.level.Level;
/**
* Apache Commons Logging
* @author Looly
*
* @author Looly
*/
public class ApacheCommonsLog extends AbstractLog {
private static final long serialVersionUID = -6843151523380063975L;
@ -19,15 +19,32 @@ public class ApacheCommonsLog extends AbstractLog {
private final String name;
// ------------------------------------------------------------------------- Constructor
/**
* 构造
*
* @param logger Logger
* @param name 名称
*/
public ApacheCommonsLog(final Log logger, final String name) {
this.logger = logger;
this.name = name;
}
/**
* 构造
*
* @param clazz
*/
public ApacheCommonsLog(final Class<?> clazz) {
this(LogFactory.getLog(clazz), null == clazz ? StrUtil.NULL : clazz.getName());
}
/**
* 构造
*
* @param name 名称
*/
public ApacheCommonsLog(final String name) {
this(LogFactory.getLog(name), name);
}
@ -46,7 +63,7 @@ public class ApacheCommonsLog extends AbstractLog {
@Override
public void trace(final String fqcn, final Throwable t, final String format, final Object... arguments) {
// fqcn此处无效
if(isTraceEnabled()){
if (isTraceEnabled()) {
logger.trace(StrUtil.format(format, arguments), t);
}
}
@ -60,7 +77,7 @@ public class ApacheCommonsLog extends AbstractLog {
@Override
public void debug(final String fqcn, final Throwable t, final String format, final Object... arguments) {
// fqcn此处无效
if(isDebugEnabled()){
if (isDebugEnabled()) {
logger.debug(StrUtil.format(format, arguments), t);
}
}
@ -74,7 +91,7 @@ public class ApacheCommonsLog extends AbstractLog {
@Override
public void info(final String fqcn, final Throwable t, final String format, final Object... arguments) {
// fqcn此处无效
if(isInfoEnabled()){
if (isInfoEnabled()) {
logger.info(StrUtil.format(format, arguments), t);
}
}
@ -87,7 +104,7 @@ public class ApacheCommonsLog extends AbstractLog {
@Override
public void warn(final String format, final Object... arguments) {
if(isWarnEnabled()){
if (isWarnEnabled()) {
logger.warn(StrUtil.format(format, arguments));
}
}
@ -99,7 +116,7 @@ public class ApacheCommonsLog extends AbstractLog {
@Override
public void warn(final String fqcn, final Throwable t, final String format, final Object... arguments) {
// fqcn此处无效
if(isWarnEnabled()){
if (isWarnEnabled()) {
logger.warn(StrUtil.format(format, arguments), t);
}
}
@ -113,7 +130,7 @@ public class ApacheCommonsLog extends AbstractLog {
@Override
public void error(final String fqcn, final Throwable t, final String format, final Object... arguments) {
// fqcn此处无效
if(isErrorEnabled()){
if (isErrorEnabled()) {
logger.warn(StrUtil.format(format, arguments), t);
}

View File

@ -7,21 +7,37 @@ import cn.hutool.log.dialect.log4j.Log4jLog;
/**
* Apache Commons Logging for Log4j
* @author Looly
*
* @author Looly
*/
public class ApacheCommonsLog4JLog extends Log4jLog {
private static final long serialVersionUID = -6843151523380063975L;
// ------------------------------------------------------------------------- Constructor
/**
* 构造
*
* @param logger Logger
*/
public ApacheCommonsLog4JLog(final Log logger) {
super(((Log4JLogger) logger).getLogger());
}
/**
* 构造
*
* @param clazz
*/
public ApacheCommonsLog4JLog(final Class<?> clazz) {
super(clazz);
}
/**
* 构造
*
* @param name 名称
*/
public ApacheCommonsLog4JLog(final String name) {
super(name);
}

View File

@ -10,6 +10,9 @@ import cn.hutool.log.LogFactory;
*/
public class ApacheCommonsLogFactory extends LogFactory{
/**
* 构造
*/
public ApacheCommonsLogFactory() {
super("Apache Common Logging");
checkLogExist(org.apache.commons.logging.LogFactory.class);

View File

@ -14,12 +14,13 @@ import org.tinylog.provider.ProviderRegistry;
* <a href="http://www.tinylog.org/">tinylog</a> log.<br>
*
* @author Looly
*
*/
public class TinyLog2 extends AbstractLog {
private static final long serialVersionUID = 1L;
/** 堆栈增加层数,因为封装因此多了两层,此值用于正确获取当前类名 */
/**
* 堆栈增加层数因为封装因此多了两层此值用于正确获取当前类名
*/
private static final int DEPTH = 5;
private final int level;
@ -31,10 +32,21 @@ public class TinyLog2 extends AbstractLog {
Configuration.getLocale(),
Configuration.isEscapingEnabled()
);
/**
* 构造
*
* @param clazz class
*/
public TinyLog2(final Class<?> clazz) {
this(null == clazz ? StrUtil.NULL : clazz.getName());
}
/**
* 构造
*
* @param name 名称
*/
public TinyLog2(final String name) {
this.name = name;
this.level = provider.getMinimumLevel().ordinal();
@ -66,6 +78,7 @@ public class TinyLog2 extends AbstractLog {
public void debug(final String fqcn, final Throwable t, final String format, final Object... arguments) {
logIfEnabled(fqcn, Level.DEBUG, t, format, arguments);
}
// ------------------------------------------------------------------------- Info
@Override
public boolean isInfoEnabled() {
@ -112,15 +125,17 @@ public class TinyLog2 extends AbstractLog {
/**
* 在对应日志级别打开情况下打印日志
*
* @param fqcn 完全限定类名(Fully Qualified Class Name)用于定位日志位置
* @param level 日志级别
* @param t 异常null则检查最后一个参数是否为Throwable类型是则取之否则不打印堆栈
* @param format 日志消息模板
* @param arguments 日志消息参数
*/
@SuppressWarnings("unused")
private void logIfEnabled(final String fqcn, final Level level, Throwable t, final String format, final Object... arguments) {
// fqcn 无效
if(null == t){
if (null == t) {
t = getLastArgumentIfThrowable(arguments);
}
provider.log(DEPTH, null, level, t, formatter, StrUtil.toString(format), arguments);

View File

@ -7,5 +7,16 @@ package cn.hutool.poi.excel.style;
* @since 4.1.0
*/
public enum Align {
LEFT, RIGHT, CENTER
/**
* 左对齐
*/
LEFT,
/**
* 右对齐
*/
RIGHT,
/**
* 居中
*/
CENTER
}

View File

@ -14,7 +14,7 @@ import cn.hutool.socket.aio.AioSession;
public interface MsgDecoder<T> {
/**
* 对于从Socket流中获取到的数据采用当前MsgDecoder的实现类协议进行解析
*
* <p>
*
* @param session 本次需要解码的session
* @param readBuffer 待处理的读buffer

View File

@ -31,6 +31,7 @@ public enum ScaleType {
*/
AREA_AVERAGING(Image.SCALE_AREA_AVERAGING);
private final int value;
/**
* 构造
*
@ -45,8 +46,6 @@ public enum ScaleType {
this.value = value;
}
private final int value;
/**
* 获取值
*

View File

@ -10,8 +10,15 @@ import java.util.LinkedHashMap;
* @author Tom Xin
*/
public class Ansi4bitMapping extends AnsiLabMapping {
/**
* 单例
*/
public static final Ansi4bitMapping INSTANCE = new Ansi4bitMapping();
/**
* 构造
*/
public Ansi4bitMapping() {
ansiLabMap = new LinkedHashMap<>(16, 1);
ansiLabMap.put(Ansi4BitColor.BLACK, new LabColor(0x000000));

View File

@ -38,8 +38,14 @@ public class Ansi8bitMapping extends AnsiLabMapping {
0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e, 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada,
0xe4e4e4, 0xeeeeee };
/**
* 单例
*/
public static final Ansi8bitMapping INSTANCE = new Ansi8bitMapping();
/**
* 构造
*/
public Ansi8bitMapping() {
ansiLabMap = new LinkedHashMap<>(256, 1);
for (int i = 0; i < ANSI_8BIT_COLOR_CODE_LOOKUP.length; i++) {