mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
5b559d19bd
commit
48eec2a8ae
@ -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>
|
||||
|
@ -42,6 +42,9 @@ import java.util.Set;
|
||||
*/
|
||||
public class Hutool {
|
||||
|
||||
/**
|
||||
* 作者(贡献者)
|
||||
*/
|
||||
public static final String AUTHOR = "Looly";
|
||||
|
||||
private Hutool() {
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
* 你 =》 \u4f60
|
||||
* </pre>
|
||||
*
|
||||
* @param value int值,也可以是char
|
||||
@ -278,7 +278,7 @@ public class HexUtil {
|
||||
* 转换的字符串如果u后不足4位,则前面用0填充,例如:
|
||||
*
|
||||
* <pre>
|
||||
* '你' =》'\u4f60'
|
||||
* 你 =》 \u4f60
|
||||
* </pre>
|
||||
*
|
||||
* @param ch char值
|
||||
|
@ -81,7 +81,7 @@ public class Base16Codec implements Encoder<byte[], char[]>, Decoder<CharSequenc
|
||||
* 转换的字符串如果u后不足4位,则前面用0填充,例如:
|
||||
*
|
||||
* <pre>
|
||||
* '你' =》'\u4f60'
|
||||
* 你 =》\u4f60
|
||||
* </pre>
|
||||
*
|
||||
* @param ch char值
|
||||
|
@ -7,7 +7,7 @@ import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Base32 - encodes and decodes RFC4648 Base32<br>
|
||||
* (see <a href="https://datatracker.ietf.org/doc/html/rfc4648#section-6">https://datatracker.ietf.org/doc/html/rfc4648#section-6</a> )<br>
|
||||
* (see <a href="https://datatracker.ietf.org/doc/html/rfc4648#section-6">https://datatracker.ietf.org/doc/html/rfc4648#section-6</a> )<br>
|
||||
* base32就是用32(2的5次方)个特定ASCII码来表示256个ASCII码。<br>
|
||||
* 所以,5个ASCII字符经过base32编码后会变为8个字符(公约数为40),长度增加3/5.不足8n用“=”补足。<br>
|
||||
* 根据RFC4648 Base32规范,支持两种模式:
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
}
|
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* MetroHash算法实现<br>
|
||||
* <p>
|
||||
* 参考:https://github.com/postamar/java-metrohash
|
||||
*
|
||||
* @author postamar, looly
|
||||
*/
|
||||
package cn.hutool.core.codec.hash.metro;
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -39,7 +39,7 @@ public enum AnsiStyle implements AnsiElement {
|
||||
|
||||
private final int code;
|
||||
|
||||
AnsiStyle(int code) {
|
||||
AnsiStyle(final int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
/**
|
||||
|
@ -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 > -∞}";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 < +∞}";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package cn.hutool.core.math;
|
||||
/**
|
||||
* 通过位运算表示状态的工具类<br>
|
||||
* 参数必须是 `偶数` 且 `大于等于0`!
|
||||
*
|
||||
* <p>
|
||||
* 工具实现见博客:https://blog.starxg.com/2020/11/bit-status/
|
||||
*
|
||||
* @author huangxingguang,senssic
|
||||
|
@ -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 },
|
||||
|
@ -893,7 +893,7 @@ public class ReUtil {
|
||||
/**
|
||||
* 替换所有正则匹配的文本,并使用自定义函数决定如何替换<br>
|
||||
* replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分,然后经过重新处理、组装变成新的内容放回原位。
|
||||
*
|
||||
* <p>
|
||||
* <pre class="code">
|
||||
* replaceAll(this.content, "(\\d+)", parameters -> "-" + 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 -> "-" + parameters.group(1) + "-")
|
||||
* // 结果为:"ZZZaaabbbccc中文-1234-"
|
||||
|
@ -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);
|
||||
|
@ -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", " " }, // non-breaking space
|
||||
{ "\u00A1", "¡" }, // inverted exclamation mark
|
||||
@ -111,6 +112,7 @@ public class Html4Escape extends XmlEscape {
|
||||
{ "\u00FF", "ÿ" }, // <EFBFBD> - lowercase y, umlaut
|
||||
};
|
||||
|
||||
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
||||
protected static final String[][] HTML40_EXTENDED_ESCAPE = {
|
||||
// <!-- Latin Extended-B -->
|
||||
{ "\u0192", "ƒ" }, // latin small f with hook = function= florin, U+0192 ISOtech -->
|
||||
@ -308,6 +310,9 @@ public class Html4Escape extends XmlEscape {
|
||||
{ "\u20AC", "€" }, // -- euro sign, U+20AC NEW -->
|
||||
};
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public Html4Escape() {
|
||||
super();
|
||||
addChain(new LookupReplacer(ISO8859_1_ESCAPE));
|
||||
|
@ -9,7 +9,7 @@ import java.util.function.Consumer;
|
||||
* 当任务队列过长时处于阻塞状态,直到添加到队列中
|
||||
* 如果阻塞过程中被中断,就会抛出{@link InterruptedException}异常<br>
|
||||
* 有时候在线程池内访问第三方接口,只希望固定并发数去访问,并且不希望丢弃任务时使用此策略,队列满的时候会处于阻塞状态(例如刷库的场景)
|
||||
*
|
||||
* <p>
|
||||
* 其他系统内置的拒绝策略,见hutool定义的枚举 {@link RejectPolicy} 线程拒绝策略枚举.
|
||||
*
|
||||
* @author luozongle
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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} 单元测试
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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 = " ";
|
||||
|
@ -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(){
|
@ -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';
|
||||
|
@ -9,6 +9,9 @@ import cn.hutool.core.text.StrUtil;
|
||||
*/
|
||||
public class AlwaysTrueMatcher implements PartMatcher {
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static AlwaysTrueMatcher INSTANCE = new AlwaysTrueMatcher();
|
||||
|
||||
@Override
|
||||
|
@ -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;
|
||||
|
@ -116,7 +116,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* <p>
|
||||
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
@ -144,7 +144,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* <p>
|
||||
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
|
||||
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证
|
||||
*
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -7,7 +7,7 @@ import java.sql.SQLException;
|
||||
/**
|
||||
* 结果集处理接口<br>
|
||||
* 此接口用于实现{@link ResultSet} 转换或映射为用户指定的pojo对象
|
||||
*
|
||||
* <p>
|
||||
* 默认实现有:
|
||||
* @see EntityHandler
|
||||
* @see EntityListHandler
|
||||
@ -15,13 +15,13 @@ import java.sql.SQLException;
|
||||
* @see EntitySetHandler
|
||||
* @see NumberHandler
|
||||
* @see PageResultHandler
|
||||
*
|
||||
*
|
||||
* @author Luxiaolei
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface RsHandler<T> extends Serializable{
|
||||
|
||||
|
||||
/**
|
||||
* 处理结果集<br>
|
||||
* 结果集处理后不需要关闭
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -25,6 +25,7 @@ public class QrAsciiArt {
|
||||
this.qrConfig = qrConfig;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
||||
@Override
|
||||
public String toString() {
|
||||
final int width = matrix.getWidth();
|
||||
|
@ -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请求引擎
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -7,7 +7,7 @@ import org.junit.Test;
|
||||
|
||||
/**
|
||||
* ContentType 单元测试
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
*/
|
||||
public class ContentTypeTest {
|
||||
|
@ -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;
|
||||
|
@ -460,6 +460,7 @@ public final class InternalJSONUtil {
|
||||
* @param c 字符
|
||||
* @return 转义后的字符串
|
||||
*/
|
||||
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
||||
private static String escape(final char c) {
|
||||
switch (c) {
|
||||
case '\b':
|
||||
|
@ -10,7 +10,7 @@ import org.junit.Test;
|
||||
* 测试在bean转换时使用BeanConverter,默认忽略转换失败的字段。
|
||||
* 现阶段Converter的问题在于,无法更细粒度的控制转换失败的范围,例如Bean的一个字段为List,
|
||||
* list任意一个item转换失败都会导致这个list为null。
|
||||
*
|
||||
* <p>
|
||||
* TODO 需要在Converter中添加ConvertOption,用于更细粒度的控制转换规则
|
||||
*/
|
||||
public class Issue1200Test {
|
||||
|
@ -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\":\"\"}";
|
@ -11,7 +11,7 @@ import java.util.List;
|
||||
* 此问题原来出在BeanCopier中,判断循环引用使用了equals,并不严谨。
|
||||
* 修复后使用==判断循环引用。
|
||||
*/
|
||||
public class IssueI1H2VN {
|
||||
public class IssueI1H2VNTest {
|
||||
|
||||
@Test
|
||||
public void toBeanTest() {
|
@ -10,7 +10,7 @@ import java.time.LocalDateTime;
|
||||
/**
|
||||
* 测试带毫秒的日期转换
|
||||
*/
|
||||
public class IssueI3BS4S {
|
||||
public class IssueI3BS4STest {
|
||||
|
||||
@Test
|
||||
public void toBeanTest(){
|
@ -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() {
|
@ -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 {
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
@ -123,23 +140,23 @@ public class ApacheCommonsLog extends AbstractLog {
|
||||
@Override
|
||||
public void log(final String fqcn, final Level level, final Throwable t, final String format, final Object... arguments) {
|
||||
switch (level) {
|
||||
case TRACE:
|
||||
trace(t, format, arguments);
|
||||
break;
|
||||
case DEBUG:
|
||||
debug(t, format, arguments);
|
||||
break;
|
||||
case INFO:
|
||||
info(t, format, arguments);
|
||||
break;
|
||||
case WARN:
|
||||
warn(t, format, arguments);
|
||||
break;
|
||||
case ERROR:
|
||||
error(t, format, arguments);
|
||||
break;
|
||||
default:
|
||||
throw new Error(StrUtil.format("Can not identify level: {}", level));
|
||||
case TRACE:
|
||||
trace(t, format, arguments);
|
||||
break;
|
||||
case DEBUG:
|
||||
debug(t, format, arguments);
|
||||
break;
|
||||
case INFO:
|
||||
info(t, format, arguments);
|
||||
break;
|
||||
case WARN:
|
||||
warn(t, format, arguments);
|
||||
break;
|
||||
case ERROR:
|
||||
error(t, format, arguments);
|
||||
break;
|
||||
default:
|
||||
throw new Error(StrUtil.format("Can not identify level: {}", level));
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------- Private method
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 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);
|
||||
@ -136,26 +151,26 @@ public class TinyLog2 extends AbstractLog {
|
||||
private Level toTinyLevel(final cn.hutool.log.level.Level level) {
|
||||
final Level tinyLevel;
|
||||
switch (level) {
|
||||
case TRACE:
|
||||
tinyLevel = Level.TRACE;
|
||||
break;
|
||||
case DEBUG:
|
||||
tinyLevel = Level.DEBUG;
|
||||
break;
|
||||
case INFO:
|
||||
tinyLevel = Level.INFO;
|
||||
break;
|
||||
case WARN:
|
||||
tinyLevel = Level.WARN;
|
||||
break;
|
||||
case ERROR:
|
||||
tinyLevel = Level.ERROR;
|
||||
break;
|
||||
case OFF:
|
||||
tinyLevel = Level.OFF;
|
||||
break;
|
||||
default:
|
||||
throw new Error(StrUtil.format("Can not identify level: {}", level));
|
||||
case TRACE:
|
||||
tinyLevel = Level.TRACE;
|
||||
break;
|
||||
case DEBUG:
|
||||
tinyLevel = Level.DEBUG;
|
||||
break;
|
||||
case INFO:
|
||||
tinyLevel = Level.INFO;
|
||||
break;
|
||||
case WARN:
|
||||
tinyLevel = Level.WARN;
|
||||
break;
|
||||
case ERROR:
|
||||
tinyLevel = Level.ERROR;
|
||||
break;
|
||||
case OFF:
|
||||
tinyLevel = Level.OFF;
|
||||
break;
|
||||
default:
|
||||
throw new Error(StrUtil.format("Can not identify level: {}", level));
|
||||
}
|
||||
return tinyLevel;
|
||||
}
|
||||
|
@ -2,10 +2,21 @@ package cn.hutool.poi.excel.style;
|
||||
|
||||
/**
|
||||
* 对齐方式枚举
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public enum Align {
|
||||
LEFT, RIGHT, CENTER
|
||||
/**
|
||||
* 左对齐
|
||||
*/
|
||||
LEFT,
|
||||
/**
|
||||
* 右对齐
|
||||
*/
|
||||
RIGHT,
|
||||
/**
|
||||
* 居中
|
||||
*/
|
||||
CENTER
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import cn.hutool.socket.aio.AioSession;
|
||||
|
||||
/**
|
||||
* 消息解码器
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
* @param <T> 解码后的目标类型
|
||||
@ -14,7 +14,7 @@ import cn.hutool.socket.aio.AioSession;
|
||||
public interface MsgDecoder<T> {
|
||||
/**
|
||||
* 对于从Socket流中获取到的数据采用当前MsgDecoder的实现类协议进行解析。
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* @param session 本次需要解码的session
|
||||
* @param readBuffer 待处理的读buffer
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
|
@ -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));
|
||||
|
@ -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++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user