mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-08-18 20:38:02 +08:00
Merge remote-tracking branch 'upstream/v5-dev' into v5-dev
This commit is contained in:
@@ -43,7 +43,7 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param element 需要解析注解的元素:可以是Class、Method、Field、Constructor、ReflectPermission
|
||||
*/
|
||||
public CombinationAnnotationElement(AnnotatedElement element) {
|
||||
@@ -73,17 +73,17 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
||||
final Collection<Annotation> annotations = this.declaredAnnotationMap.values();
|
||||
return annotations.toArray(new Annotation[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
*
|
||||
* @param element 元素
|
||||
*/
|
||||
private void init(AnnotatedElement element) {
|
||||
final Annotation[] declaredAnnotations = element.getDeclaredAnnotations();
|
||||
this.declaredAnnotationMap = new HashMap<>();
|
||||
parseDeclared(declaredAnnotations);
|
||||
|
||||
|
||||
final Annotation[] annotations = element.getAnnotations();
|
||||
if(Arrays.equals(declaredAnnotations, annotations)) {
|
||||
this.annotationMap = this.declaredAnnotationMap;
|
||||
@@ -109,7 +109,7 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 进行递归解析注解,直到全部都是元注解为止
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 注解包,提供增强型注解和注解工具类
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -11,9 +11,9 @@ import cn.hutool.core.lang.func.Func0;
|
||||
*/
|
||||
public enum BeanDescCache {
|
||||
INSTANCE;
|
||||
|
||||
|
||||
private final SimpleCache<Class<?>, BeanDesc> bdCache = new SimpleCache<>();
|
||||
|
||||
|
||||
/**
|
||||
* 获得属性名和{@link BeanDesc}Map映射
|
||||
* @param beanClass Bean的类
|
||||
|
||||
@@ -13,19 +13,19 @@ public class BeanException extends RuntimeException{
|
||||
public BeanException(Throwable e) {
|
||||
super(ExceptionUtil.getMessage(e), e);
|
||||
}
|
||||
|
||||
|
||||
public BeanException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public BeanException(String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
}
|
||||
|
||||
|
||||
public BeanException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
|
||||
public BeanException(Throwable throwable, String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ import java.util.Map;
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* 表达式栗子:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
@@ -33,7 +33,7 @@ import java.util.Map;
|
||||
* person.friends[5].name
|
||||
* ['person']['friends'][5]['name']
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @since 4.0.6
|
||||
*/
|
||||
@@ -54,9 +54,9 @@ public class BeanPath implements Serializable{
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* 表达式栗子:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
@@ -64,7 +64,7 @@ public class BeanPath implements Serializable{
|
||||
* person.friends[5].name
|
||||
* ['person']['friends'][5]['name']
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
* @return BeanPath
|
||||
*/
|
||||
@@ -74,7 +74,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
*/
|
||||
public BeanPath(String expression) {
|
||||
@@ -83,7 +83,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 获取Bean中对应表达式的值
|
||||
*
|
||||
*
|
||||
* @param bean Bean对象或Map或List等
|
||||
* @return 值,如果对应值不存在,则返回null
|
||||
*/
|
||||
@@ -95,29 +95,29 @@ public class BeanPath implements Serializable{
|
||||
* 设置表达式指定位置(或filed对应)的值<br>
|
||||
* 若表达式指向一个List则设置其坐标对应位置的值,若指向Map则put对应key的值,Bean则设置字段的值<br>
|
||||
* 注意:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1. 如果为List,如果下标不大于List长度,则替换原有值,否则追加值
|
||||
* 2. 如果为数组,如果下标不大于数组长度,则替换原有值,否则追加值
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param bean Bean、Map或List
|
||||
* @param value 值
|
||||
*/
|
||||
public void set(Object bean, Object value) {
|
||||
set(bean, this.patternParts, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置表达式指定位置(或filed对应)的值<br>
|
||||
* 若表达式指向一个List则设置其坐标对应位置的值,若指向Map则put对应key的值,Bean则设置字段的值<br>
|
||||
* 注意:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1. 如果为List,如果下标不大于List长度,则替换原有值,否则追加值
|
||||
* 2. 如果为数组,如果下标不大于数组长度,则替换原有值,否则追加值
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param bean Bean、Map或List
|
||||
* @param patternParts 表达式块列表
|
||||
* @param value 值
|
||||
@@ -135,7 +135,7 @@ public class BeanPath implements Serializable{
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 获取Bean中对应表达式的值
|
||||
*
|
||||
*
|
||||
* @param patternParts 表达式分段列表
|
||||
* @param bean Bean对象或Map或List等
|
||||
* @param ignoreLast 是否忽略最后一个值,忽略最后一个值则用于set,否则用于read
|
||||
@@ -215,7 +215,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
*/
|
||||
private void init(String expression) {
|
||||
@@ -277,7 +277,7 @@ public class BeanPath implements Serializable{
|
||||
|
||||
/**
|
||||
* 对于非表达式去除单引号
|
||||
*
|
||||
*
|
||||
* @param expression 表达式
|
||||
* @return 表达式
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.Map;
|
||||
* 3. Map 转 Bean
|
||||
* 4. Map 转 Map
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
* @param <T> 目标对象类型
|
||||
@@ -33,7 +33,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/** 源对象 */
|
||||
private final Object source;
|
||||
/** 目标对象 */
|
||||
@@ -45,7 +45,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 创建BeanCopier
|
||||
*
|
||||
*
|
||||
* @param <T> 目标Bean类型
|
||||
* @param source 来源对象,可以是Bean或者Map
|
||||
* @param dest 目标Bean对象
|
||||
@@ -58,7 +58,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 创建BeanCopier
|
||||
*
|
||||
*
|
||||
* @param <T> 目标Bean类型
|
||||
* @param source 来源对象,可以是Bean或者Map
|
||||
* @param dest 目标Bean对象
|
||||
@@ -72,7 +72,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param source 来源对象,可以是Bean或者Map
|
||||
* @param dest 目标Bean对象
|
||||
* @param destType 目标的泛型类型,用于标注有泛型参数的Bean对象
|
||||
@@ -115,7 +115,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* Bean和Bean之间属性拷贝
|
||||
*
|
||||
*
|
||||
* @param providerBean 来源Bean
|
||||
* @param destBean 目标Bean
|
||||
*/
|
||||
@@ -125,7 +125,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* Map转Bean属性拷贝
|
||||
*
|
||||
*
|
||||
* @param map Map
|
||||
* @param bean Bean
|
||||
*/
|
||||
@@ -138,7 +138,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* Map转Map
|
||||
*
|
||||
*
|
||||
* @param source 源Map
|
||||
* @param dest 目标Map
|
||||
*/
|
||||
@@ -151,7 +151,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
|
||||
/**
|
||||
* 对象转Map
|
||||
*
|
||||
*
|
||||
* @param bean bean对象
|
||||
* @param targetMap 目标的Map
|
||||
* @since 4.1.22
|
||||
@@ -201,7 +201,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
/**
|
||||
* 值提供器转Bean<br>
|
||||
* 此方法通过遍历目标Bean的字段,从ValueProvider查找对应值
|
||||
*
|
||||
*
|
||||
* @param valueProvider 值提供器
|
||||
* @param bean Bean
|
||||
*/
|
||||
|
||||
@@ -6,17 +6,17 @@ import java.lang.reflect.Type;
|
||||
* 值提供者,用于提供Bean注入时参数对应值得抽象接口<br>
|
||||
* 继承或匿名实例化此接口<br>
|
||||
* 在Bean注入过程中,Bean获得字段名,通过外部方式根据这个字段名查找相应的字段值,然后注入Bean<br>
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @param <T> KEY类型,一般情况下为 {@link String}
|
||||
*
|
||||
*/
|
||||
public interface ValueProvider<T>{
|
||||
|
||||
|
||||
/**
|
||||
* 获取值<br>
|
||||
* 返回值一般需要匹配被注入类型,如果不匹配会调用默认转换 Convert#convert(Type, Object)实现转换
|
||||
*
|
||||
*
|
||||
* @param key Bean对象中参数名
|
||||
* @param valueType 被注入的值的类型
|
||||
* @return 对应参数名的值
|
||||
@@ -26,7 +26,7 @@ public interface ValueProvider<T>{
|
||||
/**
|
||||
* 是否包含指定KEY,如果不包含则忽略注入<br>
|
||||
* 此接口方法单独需要实现的意义在于:有些值提供者(比如Map)key是存在的,但是value为null,此时如果需要注入这个null,需要根据此方法判断
|
||||
*
|
||||
*
|
||||
* @param key Bean对象中参数名
|
||||
* @return 是否包含指定KEY
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Bean拷贝实现,包括拷贝选项等
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Bean值提供者方式封装
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Bean相关操作,包括Bean信息描述,Bean路径表达式、动态Bean、Bean工具等
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 建造者模式接口定义
|
||||
*
|
||||
*
|
||||
* @param <T> 建造对象类型
|
||||
* @author Looly
|
||||
* @since 4.2.2
|
||||
@@ -12,7 +12,7 @@ import java.io.Serializable;
|
||||
public interface Builder<T> extends Serializable{
|
||||
/**
|
||||
* 构建
|
||||
*
|
||||
*
|
||||
* @return 被构建的对象
|
||||
*/
|
||||
T build();
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
/**
|
||||
* 用于构建 {@link java.lang.Comparable#compareTo(Object)} 方法的辅助工具
|
||||
*
|
||||
* <p>
|
||||
@@ -33,7 +33,7 @@ import java.util.Comparator;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* 字段值按照顺序比较,如果某个字段返回非0结果,比较终止,使用{@code toComparison()}返回结果,后续比较忽略。
|
||||
*
|
||||
* <p>
|
||||
@@ -52,7 +52,7 @@ import java.util.Comparator;
|
||||
*/
|
||||
public class CompareToBuilder implements Builder<Integer> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/** 当前比较状态 */
|
||||
private int comparison;
|
||||
|
||||
@@ -60,12 +60,11 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* 构造,构造后调用append方法增加比较项,然后调用{@link #toComparison()}获取结果
|
||||
*/
|
||||
public CompareToBuilder() {
|
||||
super();
|
||||
comparison = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
/**
|
||||
* 通过反射比较两个Bean对象,对象字段可以为private。比较规则如下:
|
||||
*
|
||||
* <ul>
|
||||
@@ -94,7 +93,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@@ -126,7 +125,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@@ -159,7 +158,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@@ -192,7 +191,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* <p>Compares two <code>Object</code>s via reflection.</p>
|
||||
*
|
||||
* <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* is used to bypass normal access control checks. This will fail under a
|
||||
* security manager unless the appropriate permissions are set.</p>
|
||||
*
|
||||
* <ul>
|
||||
@@ -221,10 +220,10 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* @since 2.2 (2.0 as <code>reflectionCompare(Object, Object, boolean, Class)</code>)
|
||||
*/
|
||||
public static int reflectionCompare(
|
||||
final Object lhs,
|
||||
final Object rhs,
|
||||
final boolean compareTransients,
|
||||
final Class<?> reflectUpToClass,
|
||||
final Object lhs,
|
||||
final Object rhs,
|
||||
final boolean compareTransients,
|
||||
final Class<?> reflectUpToClass,
|
||||
final String... excludeFields) {
|
||||
|
||||
if (lhs == rhs) {
|
||||
@@ -249,7 +248,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
/**
|
||||
* <p>Appends to <code>builder</code> the comparison of <code>lhs</code>
|
||||
* to <code>rhs</code> using the fields defined in <code>clazz</code>.</p>
|
||||
*
|
||||
*
|
||||
* @param lhs left-hand object
|
||||
* @param rhs right-hand object
|
||||
* @param clazz <code>Class</code> that defines fields to be compared
|
||||
@@ -264,7 +263,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
final CompareToBuilder builder,
|
||||
final boolean useTransients,
|
||||
final String[] excludeFields) {
|
||||
|
||||
|
||||
final Field[] fields = clazz.getDeclaredFields();
|
||||
AccessibleObject.setAccessible(fields, true);
|
||||
for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
|
||||
@@ -300,7 +299,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
comparison = superCompareTo;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Appends to the <code>builder</code> the comparison of
|
||||
@@ -312,7 +311,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* a <code>null</code> object is less than a non-<code>null</code> object</li>
|
||||
* <li>Check the object contents</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* <p><code>lhs</code> must either be an array or implement {@link Comparable}.</p>
|
||||
*
|
||||
* @param lhs left-hand object
|
||||
@@ -441,7 +440,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
/**
|
||||
* Appends to the <code>builder</code> the comparison of
|
||||
* two <code>short</code>s.
|
||||
*
|
||||
*
|
||||
* @param lhs left-hand value
|
||||
* @param rhs right-hand value
|
||||
* @return this - used to chain append calls
|
||||
@@ -473,7 +472,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
/**
|
||||
* Appends to the <code>builder</code> the comparison of
|
||||
* two <code>byte</code>s.
|
||||
*
|
||||
*
|
||||
* @param lhs left-hand value
|
||||
* @param rhs right-hand value
|
||||
* @return this - used to chain append calls
|
||||
@@ -575,7 +574,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
public CompareToBuilder append(final Object[] lhs, final Object[] rhs) {
|
||||
return append(lhs, rhs, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Appends to the <code>builder</code> the deep comparison of
|
||||
* two <code>Object</code> arrays.</p>
|
||||
@@ -950,7 +949,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* the <code>builder</code> has judged the "left-hand" side
|
||||
* as less than, greater than, or equal to the "right-hand"
|
||||
* side.
|
||||
*
|
||||
*
|
||||
* @return final comparison result
|
||||
* @see #build()
|
||||
*/
|
||||
@@ -963,7 +962,7 @@ public class CompareToBuilder implements Builder<Integer> {
|
||||
* the <code>builder</code> has judged the "left-hand" side
|
||||
* as less than, greater than, or equal to the "right-hand"
|
||||
* side.
|
||||
*
|
||||
*
|
||||
* @return final comparison result as an Integer
|
||||
* @see #toComparison()
|
||||
* @since 3.0
|
||||
|
||||
@@ -85,17 +85,17 @@ import cn.hutool.core.util.ArrayUtil;
|
||||
*/
|
||||
public class HashCodeBuilder implements Builder<Integer> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* The default initial value to use in reflection hash code building.
|
||||
*/
|
||||
private static final int DEFAULT_INITIAL_VALUE = 17;
|
||||
|
||||
|
||||
/**
|
||||
* The default multipler value to use in reflection hash code building.
|
||||
*/
|
||||
private static final int DEFAULT_MULTIPLIER_VALUE = 37;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
|
||||
@@ -103,7 +103,7 @@ public class HashCodeBuilder implements Builder<Integer> {
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<Set<IDKey>>();
|
||||
private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<>();
|
||||
|
||||
/*
|
||||
* NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
|
||||
@@ -380,7 +380,7 @@ public class HashCodeBuilder implements Builder<Integer> {
|
||||
* if the object is <code>null</code>
|
||||
*/
|
||||
public static int reflectionHashCode(final Object object, final boolean testTransients) {
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
|
||||
testTransients, null);
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ public class HashCodeBuilder implements Builder<Integer> {
|
||||
* if the object is <code>null</code>
|
||||
*/
|
||||
public static int reflectionHashCode(final Object object, final String... excludeFields) {
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
|
||||
return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
|
||||
null, excludeFields);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@ import java.io.Serializable;
|
||||
*/
|
||||
final class IDKey implements Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final Object value;
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param obj 计算唯一ID的对象
|
||||
*/
|
||||
public IDKey(final Object obj) {
|
||||
@@ -32,7 +32,7 @@ final class IDKey implements Serializable{
|
||||
|
||||
/**
|
||||
* returns hashcode - i.e. the system identity hashcode.
|
||||
*
|
||||
*
|
||||
* @return the hashcode
|
||||
*/
|
||||
@Override
|
||||
@@ -42,7 +42,7 @@ final class IDKey implements Serializable{
|
||||
|
||||
/**
|
||||
* checks if instances are equal
|
||||
*
|
||||
*
|
||||
* @param other The other object to compare to
|
||||
* @return if the instances are for the same object
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 建造者工具<br>
|
||||
* 用于建造特定对象或结果
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -13,19 +13,19 @@ public class CloneRuntimeException extends RuntimeException{
|
||||
public CloneRuntimeException(Throwable e) {
|
||||
super(ExceptionUtil.getMessage(e), e);
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
|
||||
public CloneRuntimeException(Throwable throwable, String messageTemplate, Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package cn.hutool.core.clone;
|
||||
* @param <T> 继承类的类型
|
||||
*/
|
||||
public class CloneSupport<T> implements Cloneable<T>{
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T clone() {
|
||||
@@ -17,5 +17,5 @@ public class CloneSupport<T> implements Cloneable<T>{
|
||||
throw new CloneRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package cn.hutool.core.clone;
|
||||
* @param <T> 实现克隆接口的类型
|
||||
*/
|
||||
public interface Cloneable<T> extends java.lang.Cloneable{
|
||||
|
||||
|
||||
/**
|
||||
* 克隆当前对象,浅复制
|
||||
* @return 克隆后的对象
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 克隆封装
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@ import cn.hutool.core.lang.Assert;
|
||||
*
|
||||
*/
|
||||
public class BCD {
|
||||
|
||||
|
||||
/**
|
||||
* 字符串转BCD码
|
||||
* @param asc ASCII字符串
|
||||
@@ -53,7 +53,7 @@ public class BCD {
|
||||
}
|
||||
return bbt;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ASCII转BCD
|
||||
* @param ascii ASCII byte数组
|
||||
@@ -100,8 +100,8 @@ public class BCD {
|
||||
}
|
||||
return new String(temp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 转换单个byte为BCD
|
||||
|
||||
@@ -14,7 +14,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
*
|
||||
*/
|
||||
public class Base32 {
|
||||
|
||||
|
||||
private Base32() {}
|
||||
|
||||
private static final String BASE32_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
@@ -73,10 +73,10 @@ public class Base32 {
|
||||
|
||||
return base32.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base32编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base32字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -86,7 +86,7 @@ public class Base32 {
|
||||
|
||||
/**
|
||||
* base32编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -97,7 +97,7 @@ public class Base32 {
|
||||
|
||||
/**
|
||||
* base32编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -155,10 +155,10 @@ public class Base32 {
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base32解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base32字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -168,7 +168,7 @@ public class Base32 {
|
||||
|
||||
/**
|
||||
* base32解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -176,10 +176,10 @@ public class Base32 {
|
||||
public static String decodeStr(String source, String charset) {
|
||||
return StrUtil.str(decode(source), charset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* base32解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base32字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
|
||||
@@ -12,7 +12,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* Base62工具类,提供Base62的编码和解码方案<br>
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @since 4.5.9
|
||||
*/
|
||||
@@ -24,7 +24,7 @@ public class Base62 {
|
||||
// -------------------------------------------------------------------- encode
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -34,7 +34,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的Base62字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -45,7 +45,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -55,7 +55,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param in 被编码Base62的流(一般为图片流或者文件流)
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -65,7 +65,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62编码
|
||||
*
|
||||
*
|
||||
* @param file 被编码Base62的文件
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -76,7 +76,7 @@ public class Base62 {
|
||||
// -------------------------------------------------------------------- decode
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -86,7 +86,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -96,7 +96,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的Base62字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -107,7 +107,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param Base62 被解码的Base62字符串
|
||||
* @param destFile 目标文件
|
||||
* @return 目标文件
|
||||
@@ -118,7 +118,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param base62Str 被解码的Base62字符串
|
||||
* @param out 写出到的流
|
||||
* @param isCloseOut 是否关闭输出流
|
||||
@@ -129,7 +129,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* Base62解码
|
||||
*
|
||||
*
|
||||
* @param base62Str 被解码的Base62字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -139,7 +139,7 @@ public class Base62 {
|
||||
|
||||
/**
|
||||
* 解码Base62
|
||||
*
|
||||
*
|
||||
* @param base62bytes Base62输入
|
||||
* @return 解码后的bytes
|
||||
*/
|
||||
|
||||
@@ -48,16 +48,16 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 创建GMP风格的Base62编码解码器对象
|
||||
*
|
||||
*
|
||||
* @return Base62Codec
|
||||
*/
|
||||
public static Base62Codec createGmp() {
|
||||
return new Base62Codec(GMP);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建Inverted风格的Base62编码解码器对象
|
||||
*
|
||||
*
|
||||
* @return Base62Codec
|
||||
*/
|
||||
public static Base62Codec createInverted() {
|
||||
@@ -69,7 +69,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param alphabet 自定义字母表
|
||||
*/
|
||||
public Base62Codec(byte[] alphabet) {
|
||||
@@ -93,7 +93,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 解码Base62消息
|
||||
*
|
||||
*
|
||||
* @param encoded Base62内容
|
||||
* @return 消息
|
||||
*/
|
||||
@@ -105,7 +105,7 @@ public class Base62Codec implements Serializable{
|
||||
// --------------------------------------------------------------------------------------------------------------- Private method start
|
||||
/**
|
||||
* 按照字典转换bytes
|
||||
*
|
||||
*
|
||||
* @param indices 内容
|
||||
* @param dictionary 字典
|
||||
* @return 转换值
|
||||
@@ -122,7 +122,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 使用定义的字母表从源基准到目标基准
|
||||
*
|
||||
*
|
||||
* @param message 消息bytes
|
||||
* @param sourceBase 源基准长度
|
||||
* @param targetBase 目标基准长度
|
||||
@@ -167,7 +167,7 @@ public class Base62Codec implements Serializable{
|
||||
|
||||
/**
|
||||
* 估算结果长度
|
||||
*
|
||||
*
|
||||
* @param inputLength 输入长度
|
||||
* @param sourceBase 源基准长度
|
||||
* @param targetBase 目标基准长度
|
||||
|
||||
@@ -8,7 +8,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* Base64解码实现
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
@@ -41,7 +41,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -51,7 +51,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base64字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -62,7 +62,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
*
|
||||
*
|
||||
* @param source 被解码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -72,7 +72,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* 解码Base64
|
||||
*
|
||||
*
|
||||
* @param in 输入
|
||||
* @return 解码后的bytes
|
||||
*/
|
||||
@@ -85,7 +85,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* 解码Base64
|
||||
*
|
||||
*
|
||||
* @param in 输入
|
||||
* @param pos 开始位置
|
||||
* @param length 长度
|
||||
@@ -133,7 +133,7 @@ public class Base64Decoder {
|
||||
// ----------------------------------------------------------------------------------------------- Private start
|
||||
/**
|
||||
* 获取下一个有效的byte字符
|
||||
*
|
||||
*
|
||||
* @param in 输入
|
||||
* @param pos 当前位置,调用此方法后此位置保持在有效字符的下一个位置
|
||||
* @param maxPos 最大位置
|
||||
@@ -157,7 +157,7 @@ public class Base64Decoder {
|
||||
|
||||
/**
|
||||
* int包装,使之可变
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Base64编码
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
* @since 3.2.0
|
||||
*/
|
||||
@@ -40,7 +40,7 @@ public class Base64Encoder {
|
||||
// -------------------------------------------------------------------- encode
|
||||
/**
|
||||
* 编码为Base64,非URL安全的
|
||||
*
|
||||
*
|
||||
* @param arr 被编码的数组
|
||||
* @param lineSep 在76个char之后是CRLF还是EOF
|
||||
* @return 编码后的bytes
|
||||
@@ -51,7 +51,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* 编码为Base64,URL安全的
|
||||
*
|
||||
*
|
||||
* @param arr 被编码的数组
|
||||
* @param lineSep 在76个char之后是CRLF还是EOF
|
||||
* @return 编码后的bytes
|
||||
@@ -63,7 +63,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -73,7 +73,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码,URL安全
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
* @since 3.0.6
|
||||
@@ -84,7 +84,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -95,7 +95,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码,URL安全的
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @param charset 字符集
|
||||
* @return 被加密后的字符串
|
||||
@@ -107,7 +107,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
@@ -117,7 +117,7 @@ public class Base64Encoder {
|
||||
|
||||
/**
|
||||
* base64编码,URL安全的
|
||||
*
|
||||
*
|
||||
* @param source 被编码的base64字符串
|
||||
* @return 被加密后的字符串
|
||||
* @since 3.0.6
|
||||
@@ -129,7 +129,7 @@ public class Base64Encoder {
|
||||
/**
|
||||
* 编码为Base64<br>
|
||||
* 如果isMultiLine为{@code true},则每76个字符一个换行符,否则在一行显示
|
||||
*
|
||||
*
|
||||
* @param arr 被编码的数组
|
||||
* @param isMultiLine 在76个char之后是CRLF还是EOF
|
||||
* @param isUrlSafe 是否使用URL安全字符,一般为{@code false}
|
||||
|
||||
@@ -11,7 +11,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
/**
|
||||
* 莫尔斯电码的编码和解码实现<br>
|
||||
* 参考:https://github.com/TakWolf/Java-MorseCoder
|
||||
*
|
||||
*
|
||||
* @author looly, TakWolf
|
||||
* @since 4.4.1
|
||||
*/
|
||||
@@ -22,7 +22,7 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 注册莫尔斯电码表
|
||||
*
|
||||
*
|
||||
* @param abc 字母和字符
|
||||
* @param dict 二进制
|
||||
*/
|
||||
@@ -104,7 +104,7 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param dit 点表示的字符
|
||||
* @param dah 横线表示的字符
|
||||
* @param split 分隔符
|
||||
@@ -117,13 +117,13 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*
|
||||
*
|
||||
* @param text 文本
|
||||
* @return 密文
|
||||
*/
|
||||
public String encode(String text) {
|
||||
Assert.notNull(text, "Text should not be null.");
|
||||
|
||||
|
||||
text = text.toUpperCase();
|
||||
final StringBuilder morseBuilder = new StringBuilder();
|
||||
final int len = text.codePointCount(0, text.length());
|
||||
@@ -140,7 +140,7 @@ public class Morse {
|
||||
|
||||
/**
|
||||
* 解码
|
||||
*
|
||||
*
|
||||
* @param morse 莫尔斯电码
|
||||
* @return 明文
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,7 @@ package cn.hutool.core.codec;
|
||||
/**
|
||||
* RotN(rotate by N places),回转N位密码,是一种简易的替换式密码,也是过去在古罗马开发的凯撒加密的一种变体。<br>
|
||||
* 代码来自:https://github.com/orclight/jencrypt
|
||||
*
|
||||
*
|
||||
* @author looly,shuzhilong
|
||||
* @since 4.4.1
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13编码,同时编码数字
|
||||
*
|
||||
*
|
||||
* @param message 被编码的消息
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
@@ -28,7 +28,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13编码
|
||||
*
|
||||
*
|
||||
* @param message 被编码的消息
|
||||
* @param isEnocdeNumber 是否编码数字
|
||||
* @return 编码后的字符串
|
||||
@@ -39,7 +39,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* RotN编码
|
||||
*
|
||||
*
|
||||
* @param message 被编码的消息
|
||||
* @param offset 位移,常用位移13
|
||||
* @param isEnocdeNumber 是否编码数字
|
||||
@@ -57,7 +57,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13解码,同时解码数字
|
||||
*
|
||||
*
|
||||
* @param rot 被解码的消息密文
|
||||
* @return 解码后的字符串
|
||||
*/
|
||||
@@ -67,7 +67,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* Rot-13解码
|
||||
*
|
||||
*
|
||||
* @param rot 被解码的消息密文
|
||||
* @param isDecodeNumber 是否解码数字
|
||||
* @return 解码后的字符串
|
||||
@@ -78,7 +78,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* RotN解码
|
||||
*
|
||||
*
|
||||
* @param rot 被解码的消息密文
|
||||
* @param offset 位移,常用位移13
|
||||
* @param isDecodeNumber 是否解码数字
|
||||
@@ -97,7 +97,7 @@ public class Rot {
|
||||
// ------------------------------------------------------------------------------------------ Private method start
|
||||
/**
|
||||
* 解码字符
|
||||
*
|
||||
*
|
||||
* @param c 字符
|
||||
* @param offset 位移
|
||||
* @param isDecodeNumber 是否解码数字
|
||||
@@ -129,7 +129,7 @@ public class Rot {
|
||||
|
||||
/**
|
||||
* 编码字符
|
||||
*
|
||||
*
|
||||
* @param c 字符
|
||||
* @param offset 位移
|
||||
* @param isDecodeNumber 是否编码数字
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* BaseN以及BCD编码封装
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ArrayIter<E> implements Iterator<E>, Iterable<E>, Serializable{
|
||||
if(endIndex > 0 && endIndex < this.endIndex){
|
||||
this.endIndex = endIndex;
|
||||
}
|
||||
|
||||
|
||||
if(startIndex >=0 && startIndex < this.endIndex){
|
||||
this.startIndex = startIndex;
|
||||
}
|
||||
|
||||
@@ -15,15 +15,15 @@ import java.util.PriorityQueue;
|
||||
*/
|
||||
public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
private static final long serialVersionUID = 3794348988671694820L;
|
||||
|
||||
|
||||
//容量
|
||||
private final int capacity;
|
||||
private final Comparator<? super E> comparator;
|
||||
|
||||
|
||||
public BoundedPriorityQueue(int capacity) {
|
||||
this(capacity, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param capacity 容量
|
||||
@@ -63,7 +63,7 @@ public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
}
|
||||
return super.offer(e);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加多个元素<br>
|
||||
* 参数为集合的情况请使用{@link PriorityQueue#addAll}
|
||||
@@ -73,7 +73,7 @@ public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
public boolean addAll(E[] c) {
|
||||
return this.addAll(Arrays.asList(c));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return 返回排序后的列表
|
||||
*/
|
||||
@@ -82,7 +82,7 @@ public class BoundedPriorityQueue<E> extends PriorityQueue<E>{
|
||||
list.sort(comparator);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return toList().iterator();
|
||||
|
||||
@@ -2780,11 +2780,11 @@ public class CollUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 取最大值
|
||||
* 取最小值
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param coll 集合
|
||||
* @return 最大值
|
||||
* @return 最小值
|
||||
* @see Collections#min(Collection)
|
||||
* @since 4.6.5
|
||||
*/
|
||||
@@ -2988,4 +2988,25 @@ public class CollUtil {
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个{@link Collection} 是否元素和顺序相同,返回{@code true}的条件是:
|
||||
* <ul>
|
||||
* <li>两个{@link Collection}必须长度相同</li>
|
||||
* <li>两个{@link Collection}元素相同index的对象必须equals,满足{@link Objects#equals(Object, Object)}</li>
|
||||
* </ul>
|
||||
* 此方法来自Apache-Commons-Collections4。
|
||||
*
|
||||
* @param list1 列表1
|
||||
* @param list2 列表2
|
||||
* @return 是否相同
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static boolean isEqualList(final Collection<?> list1, final Collection<?> list2) {
|
||||
if (list1 == null || list2 == null || list1.size() != list2.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IterUtil.isEqualList(list1, list2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package cn.hutool.core.collection;
|
||||
|
||||
/**
|
||||
* 集合相关工具类,包括数组,是{@link CollUtil} 的别名工具类类
|
||||
*
|
||||
*
|
||||
* @author xiaoleilu
|
||||
* @see CollUtil
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 通过{@link ConcurrentHashMap}实现的线程安全HashSet
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
@@ -32,7 +32,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
/**
|
||||
* 构造<br>
|
||||
* 触发因子为默认的0.75
|
||||
*
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
*/
|
||||
public ConcurrentHashSet(int initialCapacity) {
|
||||
@@ -41,7 +41,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 加载因子。此参数决定数据增长时触发的百分比
|
||||
*/
|
||||
@@ -51,7 +51,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
*
|
||||
* @param initialCapacity 初始大小
|
||||
* @param loadFactor 触发因子。此参数决定数据增长时触发的百分比
|
||||
* @param concurrencyLevel 线程并发度
|
||||
@@ -59,7 +59,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
|
||||
public ConcurrentHashSet(int initialCapacity, float loadFactor, int concurrencyLevel) {
|
||||
map = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从已有集合中构造
|
||||
* @param iter {@link Iterable}
|
||||
|
||||
@@ -8,14 +8,14 @@ import java.util.List;
|
||||
* 复制 {@link Iterator}<br>
|
||||
* 为了解决并发情况下{@link Iterator}遍历导致的问题(当Iterator被修改会抛出ConcurrentModificationException)
|
||||
* ,故使用复制原Iterator的方式解决此问题。
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 解决方法为:在构造方法中遍历Iterator中的元素,装入新的List中然后遍历之。
|
||||
* 当然,修改这个复制后的Iterator是没有意义的,因此remove方法将会抛出异常。
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 需要注意的是,在构造此对象时需要保证原子性(原对象不被修改),最好加锁构造此对象,构造完毕后解锁。
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
* @author Looly
|
||||
@@ -25,7 +25,7 @@ public class CopiedIter<E> implements Iterator<E>, Iterable<E>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Iterator<E> listIterator;
|
||||
|
||||
|
||||
public static <V> CopiedIter<V> copyOf(Iterator<V> iterator){
|
||||
return new CopiedIter<>(iterator);
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import java.util.Iterator;
|
||||
*/
|
||||
public class EnumerationIter<E> implements Iterator<E>, Iterable<E>, Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final Enumeration<E> e;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param enumeration {@link Enumeration}对象
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@@ -612,7 +613,7 @@ public class IterUtil {
|
||||
/**
|
||||
* Enumeration转换为Iterator
|
||||
* <p>
|
||||
* Adapt the specified <code>Enumeration</code> to the <code>Iterator</code> interface
|
||||
* Adapt the specified {@code Enumeration} to the {@code Iterator} interface
|
||||
*
|
||||
* @param <E> 集合元素类型
|
||||
* @param e {@link Enumeration}
|
||||
@@ -859,4 +860,39 @@ public class IterUtil {
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个{@link Iterable} 是否元素和顺序相同,返回{@code true}的条件是:
|
||||
* <ul>
|
||||
* <li>两个{@link Iterable}必须长度相同</li>
|
||||
* <li>两个{@link Iterable}元素相同index的对象必须equals,满足{@link Objects#equals(Object, Object)}</li>
|
||||
* </ul>
|
||||
* 此方法来自Apache-Commons-Collections4。
|
||||
*
|
||||
* @param list1 列表1
|
||||
* @param list2 列表2
|
||||
* @return 是否相同
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static boolean isEqualList(final Iterable<?> list1, final Iterable<?> list2) {
|
||||
if (list1 == list2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Iterator<?> it1 = list1.iterator();
|
||||
final Iterator<?> it2 = list2.iterator();
|
||||
Object obj1;
|
||||
Object obj2;
|
||||
while (it1.hasNext() && it2.hasNext()) {
|
||||
obj1 = it1.next();
|
||||
obj2 = it2.next();
|
||||
|
||||
if (false == Objects.equals(obj1, obj2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 当两个Iterable长度不一致时返回false
|
||||
return false == (it1.hasNext() || it2.hasNext());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import java.util.Iterator;
|
||||
*/
|
||||
public class IteratorEnumeration<E> implements Enumeration<E>, Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final Iterator<E> iterator;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param iterator {@link Iterator}对象
|
||||
|
||||
@@ -17,7 +17,7 @@ import cn.hutool.core.lang.Assert;
|
||||
/**
|
||||
* 将Reader包装为一个按照行读取的Iterator<br>
|
||||
* 此对象遍历结束后,应关闭之,推荐使用方式:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* LineIterator it = null;
|
||||
* try {
|
||||
@@ -30,7 +30,7 @@ import cn.hutool.core.lang.Assert;
|
||||
* it.close();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* 此类来自于Apache Commons io
|
||||
*
|
||||
* @author looly
|
||||
@@ -45,7 +45,7 @@ public class LineIter implements Iterator<String>, Iterable<String>, Closeable,
|
||||
private String cachedLine;
|
||||
/** A flag indicating if the iterator has been fully read. */
|
||||
private boolean finished = false;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
@@ -148,7 +148,7 @@ public class LineIter implements Iterator<String>, Iterable<String>, Closeable,
|
||||
|
||||
/**
|
||||
* 重写此方法来判断是否每一行都被返回,默认全部为true
|
||||
*
|
||||
*
|
||||
* @param line 需要验证的行
|
||||
* @return 是否通过验证
|
||||
*/
|
||||
|
||||
@@ -246,7 +246,7 @@ public class ListUtil {
|
||||
// 每页条目数大于总数直接返回所有
|
||||
if (resultSize <= pageSize) {
|
||||
if (pageNo < (PageUtil.getFirstPageNo() + 1)) {
|
||||
return Collections.unmodifiableList(list);
|
||||
return unmodifiable(list);
|
||||
} else {
|
||||
// 越界直接返回空
|
||||
return new ArrayList<>(0);
|
||||
@@ -262,11 +262,11 @@ public class ListUtil {
|
||||
if (startEnd[1] > resultSize) {
|
||||
startEnd[1] = resultSize;
|
||||
if (startEnd[0] > startEnd[1]) {
|
||||
return empty();
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
}
|
||||
|
||||
return list.subList(startEnd[0], startEnd[1]);
|
||||
return sub(list, startEnd[0], startEnd[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,7 +366,8 @@ public class ListUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取集合的部分
|
||||
* 截取集合的部分<br>
|
||||
* 此方法与{@link List#subList(int, int)} 不同在于子列表是新的副本,操作子列表不会影响原列表。
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 被截取的数组
|
||||
@@ -407,8 +408,8 @@ public class ListUtil {
|
||||
end = size;
|
||||
}
|
||||
|
||||
if (step <= 1) {
|
||||
return list.subList(start, end);
|
||||
if (step < 1) {
|
||||
step = 1;
|
||||
}
|
||||
|
||||
final List<T> result = new ArrayList<>();
|
||||
|
||||
@@ -21,7 +21,6 @@ public class ComparableComparator<E extends Comparable<? super E>> implements Co
|
||||
* 构造
|
||||
*/
|
||||
public ComparableComparator() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,9 +28,9 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 类型转换器
|
||||
*
|
||||
*
|
||||
* @author xiaoleilu
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class Convert {
|
||||
|
||||
@@ -38,7 +38,7 @@ public class Convert {
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -51,17 +51,17 @@ public class Convert {
|
||||
* 转换为字符串<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static String toStr(Object value) {
|
||||
return toStr(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为String数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return String数组
|
||||
* @since 3.2.0
|
||||
@@ -74,7 +74,7 @@ public class Convert {
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为null,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -87,17 +87,17 @@ public class Convert {
|
||||
* 转换为字符<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Character toChar(Object value) {
|
||||
return toChar(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Character数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Character数组
|
||||
* @since 3.2.0
|
||||
@@ -110,7 +110,7 @@ public class Convert {
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -123,17 +123,17 @@ public class Convert {
|
||||
* 转换为byte<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Byte toByte(Object value) {
|
||||
return toByte(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Byte数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Byte数组
|
||||
* @since 3.2.0
|
||||
@@ -157,7 +157,7 @@ public class Convert {
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -170,17 +170,17 @@ public class Convert {
|
||||
* 转换为Short<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Short toShort(Object value) {
|
||||
return toShort(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Short数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Short数组
|
||||
* @since 3.2.0
|
||||
@@ -193,7 +193,7 @@ public class Convert {
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -206,17 +206,17 @@ public class Convert {
|
||||
* 转换为Number<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Number toNumber(Object value) {
|
||||
return toNumber(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Number数组
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return Number数组
|
||||
* @since 3.2.0
|
||||
@@ -229,7 +229,7 @@ public class Convert {
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -242,7 +242,7 @@ public class Convert {
|
||||
* 转换为int<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -264,7 +264,7 @@ public class Convert {
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -277,7 +277,7 @@ public class Convert {
|
||||
* 转换为long<br>
|
||||
* 如果给定的值为{@code null},或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -287,7 +287,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -299,7 +299,7 @@ public class Convert {
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -312,7 +312,7 @@ public class Convert {
|
||||
* 转换为double<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -322,7 +322,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Double数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -334,7 +334,7 @@ public class Convert {
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -347,7 +347,7 @@ public class Convert {
|
||||
* 转换为Float<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -357,7 +357,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Float数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -369,7 +369,7 @@ public class Convert {
|
||||
* 转换为boolean<br>
|
||||
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -382,7 +382,7 @@ public class Convert {
|
||||
* 转换为boolean<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -392,7 +392,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为Boolean数组<br>
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -404,7 +404,7 @@ public class Convert {
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -417,7 +417,7 @@ public class Convert {
|
||||
* 转换为BigInteger<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -429,7 +429,7 @@ public class Convert {
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -442,19 +442,19 @@ public class Convert {
|
||||
* 转换为BigDecimal<br>
|
||||
* 如果给定的值为空,或者转换失败,返回null<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static BigDecimal toBigDecimal(Object value) {
|
||||
return toBigDecimal(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Date<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param defaultValue 转换错误时的默认值
|
||||
* @return 结果
|
||||
@@ -489,7 +489,7 @@ public class Convert {
|
||||
public static LocalDateTime toLocalDateTime(Object value) {
|
||||
return toLocalDateTime(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instant<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
@@ -508,7 +508,7 @@ public class Convert {
|
||||
* 转换为Date<br>
|
||||
* 如果给定的值为空,或者转换失败,返回{@code null}<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return 结果
|
||||
* @since 4.1.6
|
||||
@@ -516,11 +516,11 @@ public class Convert {
|
||||
public static Date toDate(Object value) {
|
||||
return toDate(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
*
|
||||
*
|
||||
* @param <E> 枚举类型
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
@@ -535,7 +535,7 @@ public class Convert {
|
||||
/**
|
||||
* 转换为Enum对象<br>
|
||||
* 如果给定的值为空,或者转换失败,返回默认值{@code null}<br>
|
||||
*
|
||||
*
|
||||
* @param <E> 枚举类型
|
||||
* @param clazz Enum的Class
|
||||
* @param value 值
|
||||
@@ -547,7 +547,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换为集合类
|
||||
*
|
||||
*
|
||||
* @param collectionType 集合类型
|
||||
* @param elementType 集合中元素类型
|
||||
* @param value 被转换的值
|
||||
@@ -557,10 +557,10 @@ public class Convert {
|
||||
public static Collection<?> toCollection(Class<?> collectionType, Class<?> elementType, Object value) {
|
||||
return new CollectionConverter(collectionType, elementType).convert(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为ArrayList,元素类型默认Object
|
||||
*
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @return {@link List}
|
||||
* @since 4.1.11
|
||||
@@ -568,10 +568,10 @@ public class Convert {
|
||||
public static List<?> toList(Object value) {
|
||||
return convert(List.class, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为ArrayList
|
||||
*
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param elementType 集合中元素类型
|
||||
* @param value 被转换的值
|
||||
@@ -598,10 +598,10 @@ public class Convert {
|
||||
public static <K, V> Map<K, V> toMap(Class<K> keyType, Class<V> valueType, Object value) {
|
||||
return (Map<K, V>) new MapConverter(HashMap.class, keyType, valueType).convert(value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型,类型采用字符串表示
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param className 类的字符串表示
|
||||
* @param value 值
|
||||
@@ -612,10 +612,10 @@ public class Convert {
|
||||
public static <T> T convertByClassName(String className, Object value) throws ConvertException{
|
||||
return convert(ClassUtil.loadClass(className), value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@@ -626,10 +626,10 @@ public class Convert {
|
||||
public static <T> T convert(Class<T> type, Object value) throws ConvertException{
|
||||
return convert((Type)type, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param reference 类型参考,用于持有转换后的泛型类型
|
||||
* @param value 值
|
||||
@@ -642,7 +642,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@@ -652,10 +652,10 @@ public class Convert {
|
||||
public static <T> T convert(Type type, Object value) throws ConvertException{
|
||||
return convert(type, value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@@ -667,10 +667,10 @@ public class Convert {
|
||||
public static <T> T convert(Class<T> type, Object value, T defaultValue) throws ConvertException {
|
||||
return convert((Type)type, value, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 类型
|
||||
* @param value 值
|
||||
@@ -681,11 +681,11 @@ public class Convert {
|
||||
public static <T> T convert(Type type, Object value, T defaultValue) throws ConvertException {
|
||||
return convertWithCheck(type, value, defaultValue, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型,不抛异常转换<br>
|
||||
* 当转换失败时返回{@code null}
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 目标类型
|
||||
* @param value 值
|
||||
@@ -695,11 +695,11 @@ public class Convert {
|
||||
public static <T> T convertQuietly(Type type, Object value) {
|
||||
return convertQuietly(type, value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换值为指定类型,不抛异常转换<br>
|
||||
* 当转换失败时返回默认值
|
||||
*
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param type 目标类型
|
||||
* @param value 值
|
||||
@@ -734,11 +734,11 @@ public class Convert {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------- 全角半角转换
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
*
|
||||
* @param input String.
|
||||
* @return 全角字符串.
|
||||
*/
|
||||
@@ -748,7 +748,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 半角转全角
|
||||
*
|
||||
*
|
||||
* @param input String
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 全角字符串.
|
||||
@@ -773,7 +773,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 全角转半角
|
||||
*
|
||||
*
|
||||
* @param input String.
|
||||
* @return 半角字符串
|
||||
*/
|
||||
@@ -783,7 +783,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 替换全角为半角
|
||||
*
|
||||
*
|
||||
* @param text 文本
|
||||
* @param notConvertSet 不替换的字符集合
|
||||
* @return 替换后的字符
|
||||
@@ -813,7 +813,7 @@ public class Convert {
|
||||
// --------------------------------------------------------------------- hex
|
||||
/**
|
||||
* 字符串转换成十六进制字符串,结果为小写
|
||||
*
|
||||
*
|
||||
* @param str 待转换的ASCII字符串
|
||||
* @param charset 编码
|
||||
* @return 16进制字符串
|
||||
@@ -825,7 +825,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte数组转16进制串
|
||||
*
|
||||
*
|
||||
* @param bytes 被转换的byte数组
|
||||
* @return 转换后的值
|
||||
* @see HexUtil#encodeHexStr(byte[])
|
||||
@@ -836,7 +836,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* Hex字符串转换为Byte值
|
||||
*
|
||||
*
|
||||
* @param src Byte字符串,每个Byte之间没有分隔符
|
||||
* @return byte[]
|
||||
* @see HexUtil#decodeHex(char[])
|
||||
@@ -847,7 +847,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 十六进制转换字符串
|
||||
*
|
||||
*
|
||||
* @param hexStr Byte字符串(Byte之间无分隔符 如:[616C6B])
|
||||
* @param charset 编码 {@link Charset}
|
||||
* @return 对应的字符串
|
||||
@@ -858,10 +858,10 @@ public class Convert {
|
||||
public static String hexStrToStr(String hexStr, Charset charset) {
|
||||
return hexToStr(hexStr, charset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 十六进制转换字符串
|
||||
*
|
||||
*
|
||||
* @param hexStr Byte字符串(Byte之间无分隔符 如:[616C6B])
|
||||
* @param charset 编码 {@link Charset}
|
||||
* @return 对应的字符串
|
||||
@@ -874,7 +874,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* String的字符串转换成unicode的String
|
||||
*
|
||||
*
|
||||
* @param strText 全角字符串
|
||||
* @return String 每个unicode之间无分隔符
|
||||
* @see UnicodeUtil#toUnicode(String)
|
||||
@@ -885,7 +885,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* unicode的String转换成String的字符串
|
||||
*
|
||||
*
|
||||
* @param unicode Unicode符
|
||||
* @return String 字符串
|
||||
* @see UnicodeUtil#toString(String)
|
||||
@@ -897,7 +897,7 @@ public class Convert {
|
||||
/**
|
||||
* 给定字符串转换字符编码<br>
|
||||
* 如果参数为空,则返回原字符串,不报错。
|
||||
*
|
||||
*
|
||||
* @param str 被转码的字符串
|
||||
* @param sourceCharset 原字符集
|
||||
* @param destCharset 目标字符集
|
||||
@@ -914,7 +914,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 转换时间单位
|
||||
*
|
||||
*
|
||||
* @param sourceDuration 时长
|
||||
* @param sourceUnit 源单位
|
||||
* @param destUnit 目标单位
|
||||
@@ -929,7 +929,7 @@ public class Convert {
|
||||
// --------------------------------------------------------------- 原始包装类型转换
|
||||
/**
|
||||
* 原始类转为包装类,非原始类返回原类
|
||||
*
|
||||
*
|
||||
* @see BasicType#wrap(Class)
|
||||
* @param clazz 原始类
|
||||
* @return 包装类
|
||||
@@ -941,7 +941,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* 包装类转为原始类,非包装类返回原类
|
||||
*
|
||||
*
|
||||
* @see BasicType#unWrap(Class)
|
||||
* @param clazz 包装类
|
||||
* @return 原始类
|
||||
@@ -954,7 +954,7 @@ public class Convert {
|
||||
// -------------------------------------------------------------------------- 数字和英文转换
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达方式
|
||||
*
|
||||
*
|
||||
* @param number {@link Number}对象
|
||||
* @return 英文表达式
|
||||
* @since 3.0.9
|
||||
@@ -962,10 +962,25 @@ public class Convert {
|
||||
public static String numberToWord(Number number) {
|
||||
return NumberWordFormatter.format(number);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为精简表示形式,例如:
|
||||
*
|
||||
* <pre>
|
||||
* 1200 -》 1.2k
|
||||
* </pre>
|
||||
*
|
||||
* @param number {@link Number}对象
|
||||
* @return 英文表达式
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public static String numberToSimple(Number number) {
|
||||
return NumberWordFormatter.formatSimple(number.longValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为中文表达方式
|
||||
*
|
||||
*
|
||||
* @param number 数字
|
||||
* @param isUseTraditonal 是否使用繁体字(金额形式)
|
||||
* @return 中文
|
||||
@@ -974,10 +989,10 @@ public class Convert {
|
||||
public static String numberToChinese(double number, boolean isUseTraditonal) {
|
||||
return NumberChineseFormatter.format(number, isUseTraditonal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 金额转为中文形式
|
||||
*
|
||||
*
|
||||
* @param n 数字
|
||||
* @return 中文大写数字
|
||||
* @since 3.2.3
|
||||
@@ -988,11 +1003,11 @@ public class Convert {
|
||||
}
|
||||
return NumberChineseFormatter.format(n.doubleValue(), true, true);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------- 数字转换
|
||||
/**
|
||||
* int转byte
|
||||
*
|
||||
*
|
||||
* @param intValue int值
|
||||
* @return byte值
|
||||
* @since 3.2.0
|
||||
@@ -1003,7 +1018,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte转无符号int
|
||||
*
|
||||
*
|
||||
* @param byteValue byte值
|
||||
* @return 无符号int值
|
||||
* @since 3.2.0
|
||||
@@ -1015,7 +1030,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte数组转short
|
||||
*
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @return short值
|
||||
* @since 3.2.0
|
||||
@@ -1039,7 +1054,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* byte[]转int值
|
||||
*
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @return int值
|
||||
* @since 3.2.0
|
||||
@@ -1053,7 +1068,7 @@ public class Convert {
|
||||
|
||||
/**
|
||||
* int转byte数组
|
||||
*
|
||||
*
|
||||
* @param intValue int值
|
||||
* @return byte数组
|
||||
* @since 3.2.0
|
||||
@@ -1070,7 +1085,7 @@ public class Convert {
|
||||
/**
|
||||
* long转byte数组<br>
|
||||
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||
*
|
||||
*
|
||||
* @param longValue long值
|
||||
* @return byte数组
|
||||
* @since 3.2.0
|
||||
@@ -1088,7 +1103,7 @@ public class Convert {
|
||||
/**
|
||||
* byte数组转long<br>
|
||||
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||
*
|
||||
*
|
||||
* @param bytes byte数组
|
||||
* @return long值
|
||||
* @since 3.2.0
|
||||
|
||||
@@ -1,180 +1,182 @@
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* 将浮点数类型的number转换成英语的表达方式 <br>
|
||||
* 参考博客:http://blog.csdn.net/eric_sunah/article/details/8713226
|
||||
*
|
||||
* @author Looly
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public class NumberWordFormatter {
|
||||
|
||||
private static final String[] NUMBER = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
|
||||
"EIGHT", "NINE"};
|
||||
private static final String[] NUMBER_TEEN = new String[]{"TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN",
|
||||
"FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"};
|
||||
private static final String[] NUMBER_TEN = new String[]{"TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY",
|
||||
"SEVENTY", "EIGHTY", "NINETY"};
|
||||
private static final String[] NUMBER_MORE = new String[]{"", "THOUSAND", "MILLION", "BILLION"};
|
||||
|
||||
private static final String[] NUMBER_SUFFIX = new String[]{"k", "w", "", "m", "", "", "b", "", "", "t", "", "", "p", "", "", "e"};
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字,可以为{@link Number}对象,也可以是普通对象,最后会使用字符串方式处理
|
||||
* @return 英文表达式
|
||||
*/
|
||||
public static String format(Object x) {
|
||||
if (x != null) {
|
||||
return format(x.toString());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简介计数单位,例如 2100 => 2.1k
|
||||
* 范围默认只到w
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String formatValue(long value) {
|
||||
return formatValue(value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简介计数单位,例如 2100 => 2.1k
|
||||
* @param value 对应数字的值
|
||||
* @param isTwo 控制是否为k、w
|
||||
* @return
|
||||
*/
|
||||
public static String formatValue(long value, boolean isTwo) {
|
||||
if (value < 1000) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
int index = -1;
|
||||
double res = value * 1.0d;
|
||||
while (res > 10 && (!isTwo || index < 1)) {
|
||||
if (res > 1000) {
|
||||
res = res / 1000;
|
||||
index++;
|
||||
}
|
||||
if (res > 10) {
|
||||
res = res / 10;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||
return String.format("%s%s", decimalFormat.format(res), NUMBER_SUFFIX[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字字符串
|
||||
* @return 英文表达式
|
||||
*/
|
||||
private static String format(String x) {
|
||||
int z = x.indexOf("."); // 取小数点位置
|
||||
String lstr, rstr = "";
|
||||
if (z > -1) { // 看是否有小数,如果有,则分别取左边和右边
|
||||
lstr = x.substring(0, z);
|
||||
rstr = x.substring(z + 1);
|
||||
} else {
|
||||
// 否则就是全部
|
||||
lstr = x;
|
||||
}
|
||||
|
||||
String lstrrev = StrUtil.reverse(lstr); // 对左边的字串取反
|
||||
String[] a = new String[5]; // 定义5个字串变量来存放解析出来的叁位一组的字串
|
||||
|
||||
switch (lstrrev.length() % 3) {
|
||||
case 1:
|
||||
lstrrev += "00";
|
||||
break;
|
||||
case 2:
|
||||
lstrrev += "0";
|
||||
break;
|
||||
}
|
||||
StringBuilder lm = new StringBuilder(); // 用来存放转换后的整数部分
|
||||
for (int i = 0; i < lstrrev.length() / 3; i++) {
|
||||
a[i] = StrUtil.reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一个三位
|
||||
if (false == "000".equals(a[i])) { // 用来避免这种情况:1000000 = one million
|
||||
// thousand only
|
||||
if (i != 0) {
|
||||
lm.insert(0, transThree(a[i]) + " " + parseMore(i) + " "); // 加:
|
||||
// thousand、million、billion
|
||||
} else {
|
||||
// 防止i=0时, 在多加两个空格.
|
||||
lm = new StringBuilder(transThree(a[i]));
|
||||
}
|
||||
} else {
|
||||
lm.append(transThree(a[i]));
|
||||
}
|
||||
}
|
||||
|
||||
String xs = ""; // 用来存放转换后小数部分
|
||||
if (z > -1) {
|
||||
xs = "AND CENTS " + transTwo(rstr) + " "; // 小数部分存在时转换小数
|
||||
}
|
||||
|
||||
return lm.toString().trim() + " " + xs + "ONLY";
|
||||
}
|
||||
|
||||
private static String parseFirst(String s) {
|
||||
return NUMBER[Integer.parseInt(s.substring(s.length() - 1))];
|
||||
}
|
||||
|
||||
private static String parseTeen(String s) {
|
||||
return NUMBER_TEEN[Integer.parseInt(s) - 10];
|
||||
}
|
||||
|
||||
private static String parseTen(String s) {
|
||||
return NUMBER_TEN[Integer.parseInt(s.substring(0, 1)) - 1];
|
||||
}
|
||||
|
||||
private static String parseMore(int i) {
|
||||
return NUMBER_MORE[i];
|
||||
}
|
||||
|
||||
// 两位
|
||||
private static String transTwo(String s) {
|
||||
String value;
|
||||
// 判断位数
|
||||
if (s.length() > 2) {
|
||||
s = s.substring(0, 2);
|
||||
} else if (s.length() < 2) {
|
||||
s = "0" + s;
|
||||
}
|
||||
|
||||
if (s.startsWith("0")) {// 07 - seven 是否小於10
|
||||
value = parseFirst(s);
|
||||
} else if (s.startsWith("1")) {// 17 seventeen 是否在10和20之间
|
||||
value = parseTeen(s);
|
||||
} else if (s.endsWith("0")) {// 是否在10与100之间的能被10整除的数
|
||||
value = parseTen(s);
|
||||
} else {
|
||||
value = parseTen(s) + " " + parseFirst(s);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// 制作叁位的数
|
||||
// s.length = 3
|
||||
private static String transThree(String s) {
|
||||
String value;
|
||||
if (s.startsWith("0")) {// 是否小於100
|
||||
value = transTwo(s.substring(1));
|
||||
} else if ("00".equals(s.substring(1))) {// 是否被100整除
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED";
|
||||
} else {
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED AND " + transTwo(s.substring(1));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 将浮点数类型的number转换成英语的表达方式 <br>
|
||||
* 参考博客:http://blog.csdn.net/eric_sunah/article/details/8713226
|
||||
*
|
||||
* @author Looly,totalo
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public class NumberWordFormatter {
|
||||
|
||||
private static final String[] NUMBER = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
|
||||
"EIGHT", "NINE"};
|
||||
private static final String[] NUMBER_TEEN = new String[]{"TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN",
|
||||
"FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"};
|
||||
private static final String[] NUMBER_TEN = new String[]{"TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY",
|
||||
"SEVENTY", "EIGHTY", "NINETY"};
|
||||
private static final String[] NUMBER_MORE = new String[]{"", "THOUSAND", "MILLION", "BILLION"};
|
||||
|
||||
private static final String[] NUMBER_SUFFIX = new String[]{"k", "w", "", "m", "", "", "b", "", "", "t", "", "", "p", "", "", "e"};
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字,可以为{@link Number}对象,也可以是普通对象,最后会使用字符串方式处理
|
||||
* @return 英文表达式
|
||||
*/
|
||||
public static String format(Object x) {
|
||||
if (x != null) {
|
||||
return format(x.toString());
|
||||
} else {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简洁计数单位,例如 2100 =》 2.1k
|
||||
* 范围默认只到w
|
||||
*
|
||||
* @param value 被格式化的数字
|
||||
* @return 格式化后的数字
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public static String formatSimple(long value) {
|
||||
return formatSimple(value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转化为简介计数单位,例如 2100 =》 2.1k
|
||||
*
|
||||
* @param value 对应数字的值
|
||||
* @param isTwo 控制是否为只为k、w,例如当为{@code false}时返回4.38m,{@code true}返回438.43w
|
||||
* @return 格式化后的数字
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public static String formatSimple(long value, boolean isTwo) {
|
||||
if (value < 1000) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
int index = -1;
|
||||
double res = value;
|
||||
while (res > 10 && (false == isTwo || index < 1)) {
|
||||
if (res > 1000) {
|
||||
res = res / 1000;
|
||||
index++;
|
||||
}
|
||||
if (res > 10) {
|
||||
res = res / 10;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return String.format("%s%s", NumberUtil.decimalFormat("#.##", res), NUMBER_SUFFIX[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将阿拉伯数字转为英文表达式
|
||||
*
|
||||
* @param x 阿拉伯数字字符串
|
||||
* @return 英文表达式
|
||||
*/
|
||||
private static String format(String x) {
|
||||
int z = x.indexOf("."); // 取小数点位置
|
||||
String lstr, rstr = "";
|
||||
if (z > -1) { // 看是否有小数,如果有,则分别取左边和右边
|
||||
lstr = x.substring(0, z);
|
||||
rstr = x.substring(z + 1);
|
||||
} else {
|
||||
// 否则就是全部
|
||||
lstr = x;
|
||||
}
|
||||
|
||||
String lstrrev = StrUtil.reverse(lstr); // 对左边的字串取反
|
||||
String[] a = new String[5]; // 定义5个字串变量来存放解析出来的叁位一组的字串
|
||||
|
||||
switch (lstrrev.length() % 3) {
|
||||
case 1:
|
||||
lstrrev += "00";
|
||||
break;
|
||||
case 2:
|
||||
lstrrev += "0";
|
||||
break;
|
||||
}
|
||||
StringBuilder lm = new StringBuilder(); // 用来存放转换后的整数部分
|
||||
for (int i = 0; i < lstrrev.length() / 3; i++) {
|
||||
a[i] = StrUtil.reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一个三位
|
||||
if (false == "000".equals(a[i])) { // 用来避免这种情况:1000000 = one million
|
||||
// thousand only
|
||||
if (i != 0) {
|
||||
lm.insert(0, transThree(a[i]) + " " + parseMore(i) + " "); // 加:
|
||||
// thousand、million、billion
|
||||
} else {
|
||||
// 防止i=0时, 在多加两个空格.
|
||||
lm = new StringBuilder(transThree(a[i]));
|
||||
}
|
||||
} else {
|
||||
lm.append(transThree(a[i]));
|
||||
}
|
||||
}
|
||||
|
||||
String xs = ""; // 用来存放转换后小数部分
|
||||
if (z > -1) {
|
||||
xs = "AND CENTS " + transTwo(rstr) + " "; // 小数部分存在时转换小数
|
||||
}
|
||||
|
||||
return lm.toString().trim() + " " + xs + "ONLY";
|
||||
}
|
||||
|
||||
private static String parseFirst(String s) {
|
||||
return NUMBER[Integer.parseInt(s.substring(s.length() - 1))];
|
||||
}
|
||||
|
||||
private static String parseTeen(String s) {
|
||||
return NUMBER_TEEN[Integer.parseInt(s) - 10];
|
||||
}
|
||||
|
||||
private static String parseTen(String s) {
|
||||
return NUMBER_TEN[Integer.parseInt(s.substring(0, 1)) - 1];
|
||||
}
|
||||
|
||||
private static String parseMore(int i) {
|
||||
return NUMBER_MORE[i];
|
||||
}
|
||||
|
||||
// 两位
|
||||
private static String transTwo(String s) {
|
||||
String value;
|
||||
// 判断位数
|
||||
if (s.length() > 2) {
|
||||
s = s.substring(0, 2);
|
||||
} else if (s.length() < 2) {
|
||||
s = "0" + s;
|
||||
}
|
||||
|
||||
if (s.startsWith("0")) {// 07 - seven 是否小於10
|
||||
value = parseFirst(s);
|
||||
} else if (s.startsWith("1")) {// 17 seventeen 是否在10和20之间
|
||||
value = parseTeen(s);
|
||||
} else if (s.endsWith("0")) {// 是否在10与100之间的能被10整除的数
|
||||
value = parseTen(s);
|
||||
} else {
|
||||
value = parseTen(s) + " " + parseFirst(s);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// 制作叁位的数
|
||||
// s.length = 3
|
||||
private static String transThree(String s) {
|
||||
String value;
|
||||
if (s.startsWith("0")) {// 是否小於100
|
||||
value = transTwo(s.substring(1));
|
||||
} else if ("00".equals(s.substring(1))) {// 是否被100整除
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED";
|
||||
} else {
|
||||
value = parseFirst(s.substring(0, 1)) + " HUNDRED AND " + transTwo(s.substring(1));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,7 +694,6 @@ public class FastDatePrinter extends AbstractDateBasic implements DatePrinter {
|
||||
*
|
||||
*/
|
||||
UnpaddedMonthField() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -833,7 +832,6 @@ public class FastDatePrinter extends AbstractDateBasic implements DatePrinter {
|
||||
* Constructs an instance of {@code TwoDigitYearField}.
|
||||
*/
|
||||
TwoDigitYearField() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -873,7 +871,6 @@ public class FastDatePrinter extends AbstractDateBasic implements DatePrinter {
|
||||
* Constructs an instance of {@code TwoDigitMonthField}.
|
||||
*/
|
||||
TwoDigitMonthField() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,6 @@ public final class FastStringWriter extends Writer {
|
||||
* @param initialSize 初始容量
|
||||
*/
|
||||
public FastStringWriter(int initialSize) {
|
||||
super();
|
||||
if (initialSize < 0) {
|
||||
initialSize = StrBuilder.DEFAULT_CAPACITY;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
@@ -23,7 +23,15 @@ public class FileTypeUtil {
|
||||
private static final Map<String, String> FILE_TYPE_MAP;
|
||||
|
||||
static {
|
||||
FILE_TYPE_MAP = new ConcurrentHashMap<>();
|
||||
FILE_TYPE_MAP = new ConcurrentSkipListMap<>((s1, s2) -> {
|
||||
int len1 = s1.length();
|
||||
int len2 = s2.length();
|
||||
if (len1 == len2) {
|
||||
return s1.compareTo(s2);
|
||||
} else {
|
||||
return len2 - len1;
|
||||
}
|
||||
});
|
||||
|
||||
FILE_TYPE_MAP.put("ffd8ff", "jpg"); // JPEG (jpg)
|
||||
FILE_TYPE_MAP.put("89504e47", "png"); // PNG (png)
|
||||
@@ -50,22 +58,23 @@ public class FileTypeUtil {
|
||||
FILE_TYPE_MAP.put("52494646e27807005741", "wav"); // Wave (wav)
|
||||
FILE_TYPE_MAP.put("52494646d07d60074156", "avi");
|
||||
FILE_TYPE_MAP.put("4d546864000000060001", "mid"); // MIDI (mid)
|
||||
FILE_TYPE_MAP.put("526172211a0700cf9073", "rar");// WinRAR
|
||||
FILE_TYPE_MAP.put("526172211a0700cf9073", "rar"); // WinRAR
|
||||
FILE_TYPE_MAP.put("235468697320636f6e66", "ini");
|
||||
FILE_TYPE_MAP.put("504B0304140000000800", "ofd"); // ofd文件 国标版式文件
|
||||
FILE_TYPE_MAP.put("504B03040a0000000000", "jar");
|
||||
FILE_TYPE_MAP.put("504B0304140008000800", "jar");
|
||||
// MS Excel 注意:word、msi 和 excel的文件头一样
|
||||
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10", "xls");
|
||||
FILE_TYPE_MAP.put("504B0304", "zip");
|
||||
FILE_TYPE_MAP.put("4d5a9000030000000400", "exe");// 可执行文件
|
||||
FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");// jsp文件
|
||||
FILE_TYPE_MAP.put("4d616e69666573742d56", "mf");// MF文件
|
||||
FILE_TYPE_MAP.put("7061636b616765207765", "java");// java文件
|
||||
FILE_TYPE_MAP.put("406563686f206f66660d", "bat");// bat文件
|
||||
FILE_TYPE_MAP.put("1f8b0800000000000000", "gz");// gz文件
|
||||
FILE_TYPE_MAP.put("cafebabe0000002e0041", "class");// bat文件
|
||||
FILE_TYPE_MAP.put("49545346030000006000", "chm");// bat文件
|
||||
FILE_TYPE_MAP.put("04000000010000001300", "mxp");// bat文件
|
||||
FILE_TYPE_MAP.put("4d5a9000030000000400", "exe"); // 可执行文件
|
||||
FILE_TYPE_MAP.put("3c25402070616765206c", "jsp"); // jsp文件
|
||||
FILE_TYPE_MAP.put("4d616e69666573742d56", "mf"); // MF文件
|
||||
FILE_TYPE_MAP.put("7061636b616765207765", "java"); // java文件
|
||||
FILE_TYPE_MAP.put("406563686f206f66660d", "bat"); // bat文件
|
||||
FILE_TYPE_MAP.put("1f8b0800000000000000", "gz"); // gz文件
|
||||
FILE_TYPE_MAP.put("cafebabe0000002e0041", "class"); // class文件
|
||||
FILE_TYPE_MAP.put("49545346030000006000", "chm"); // chm文件
|
||||
FILE_TYPE_MAP.put("04000000010000001300", "mxp"); // mxp文件
|
||||
FILE_TYPE_MAP.put("6431303a637265617465", "torrent");
|
||||
FILE_TYPE_MAP.put("6D6F6F76", "mov"); // Quicktime (mov)
|
||||
FILE_TYPE_MAP.put("FF575043", "wpd"); // WordPerfect (wpd)
|
||||
@@ -85,7 +94,7 @@ public class FileTypeUtil {
|
||||
* @return 之前已经存在的文件扩展名
|
||||
*/
|
||||
public static String putFileType(String fileStreamHexHead, String extName) {
|
||||
return FILE_TYPE_MAP.put(fileStreamHexHead.toLowerCase(), extName);
|
||||
return FILE_TYPE_MAP.put(fileStreamHexHead, extName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +104,7 @@ public class FileTypeUtil {
|
||||
* @return 移除的文件扩展名
|
||||
*/
|
||||
public static String removeFileType(String fileStreamHexHead) {
|
||||
return FILE_TYPE_MAP.remove(fileStreamHexHead.toLowerCase());
|
||||
return FILE_TYPE_MAP.remove(fileStreamHexHead);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,6 @@ public class MultiFileResource extends MultiResource{
|
||||
* @param files 文件资源列表
|
||||
*/
|
||||
public MultiFileResource(Collection<File> files) {
|
||||
super();
|
||||
add(files);
|
||||
}
|
||||
|
||||
@@ -29,7 +28,6 @@ public class MultiFileResource extends MultiResource{
|
||||
* @param files 文件资源列表
|
||||
*/
|
||||
public MultiFileResource(File... files) {
|
||||
super();
|
||||
add(files);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public enum DataUnit {
|
||||
*/
|
||||
TERABYTES("TB", DataSize.ofTerabytes(1));
|
||||
|
||||
public static final String[] UNIT_NAMES = new String[]{"B", "kB", "MB", "GB", "TB", "EB"};
|
||||
public static final String[] UNIT_NAMES = new String[]{"B", "kB", "MB", "GB", "TB", "PB", "EB"};
|
||||
|
||||
private final String suffix;
|
||||
|
||||
@@ -77,4 +77,4 @@ public enum DataUnit {
|
||||
throw new IllegalArgumentException("Unknown data unit suffix '" + suffix + "'");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ public final class Holder<T> extends MutableObj<T>{
|
||||
* 构造
|
||||
*/
|
||||
public Holder() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableBool implements Comparable<MutableBool>, Mutable<Boolean>, S
|
||||
* 构造,默认值0
|
||||
*/
|
||||
public MutableBool() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public class MutableBool implements Comparable<MutableBool>, Mutable<Boolean>, S
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableBool(final boolean value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -35,7 +33,6 @@ public class MutableBool implements Comparable<MutableBool>, Mutable<Boolean>, S
|
||||
* @throws NumberFormatException 转为Boolean错误
|
||||
*/
|
||||
public MutableBool(final String value) throws NumberFormatException {
|
||||
super();
|
||||
this.value = Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableByte extends Number implements Comparable<MutableByte>, Muta
|
||||
* 构造,默认值0
|
||||
*/
|
||||
public MutableByte() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public class MutableByte extends Number implements Comparable<MutableByte>, Muta
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableByte(final byte value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -43,7 +41,6 @@ public class MutableByte extends Number implements Comparable<MutableByte>, Muta
|
||||
* @throws NumberFormatException 转为Byte错误
|
||||
*/
|
||||
public MutableByte(final String value) throws NumberFormatException {
|
||||
super();
|
||||
this.value = Byte.parseByte(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableDouble extends Number implements Comparable<MutableDouble>,
|
||||
* 构造,默认值0
|
||||
*/
|
||||
public MutableDouble() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public class MutableDouble extends Number implements Comparable<MutableDouble>,
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableDouble(final double value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -43,7 +41,6 @@ public class MutableDouble extends Number implements Comparable<MutableDouble>,
|
||||
* @throws NumberFormatException 数字转换错误
|
||||
*/
|
||||
public MutableDouble(final String value) throws NumberFormatException {
|
||||
super();
|
||||
this.value = Double.parseDouble(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableFloat extends Number implements Comparable<MutableFloat>, Mu
|
||||
* 构造,默认值0
|
||||
*/
|
||||
public MutableFloat() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public class MutableFloat extends Number implements Comparable<MutableFloat>, Mu
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableFloat(final float value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -43,7 +41,6 @@ public class MutableFloat extends Number implements Comparable<MutableFloat>, Mu
|
||||
* @throws NumberFormatException 数字转换错误
|
||||
*/
|
||||
public MutableFloat(final String value) throws NumberFormatException {
|
||||
super();
|
||||
this.value = Float.parseFloat(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableInt extends Number implements Comparable<MutableInt>, Mutabl
|
||||
* 构造,默认值0
|
||||
*/
|
||||
public MutableInt() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public class MutableInt extends Number implements Comparable<MutableInt>, Mutabl
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableInt(final int value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -43,7 +41,6 @@ public class MutableInt extends Number implements Comparable<MutableInt>, Mutabl
|
||||
* @throws NumberFormatException 数字转换错误
|
||||
*/
|
||||
public MutableInt(final String value) throws NumberFormatException {
|
||||
super();
|
||||
this.value = Integer.parseInt(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableLong extends Number implements Comparable<MutableLong>, Muta
|
||||
* 构造,默认值0
|
||||
*/
|
||||
public MutableLong() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public class MutableLong extends Number implements Comparable<MutableLong>, Muta
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableLong(final long value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -43,7 +41,6 @@ public class MutableLong extends Number implements Comparable<MutableLong>, Muta
|
||||
* @throws NumberFormatException 数字转换错误
|
||||
*/
|
||||
public MutableLong(final String value) throws NumberFormatException {
|
||||
super();
|
||||
this.value = Long.parseLong(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableObj<T> implements Mutable<T>, Serializable {
|
||||
* 构造,空值
|
||||
*/
|
||||
public MutableObj() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,7 +25,6 @@ public class MutableObj<T> implements Mutable<T>, Serializable {
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableObj(final T value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ public class MutableShort extends Number implements Comparable<MutableShort>, Mu
|
||||
* 构造,默认值0
|
||||
*/
|
||||
public MutableShort() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public class MutableShort extends Number implements Comparable<MutableShort>, Mu
|
||||
* @param value 值
|
||||
*/
|
||||
public MutableShort(final short value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -43,7 +41,6 @@ public class MutableShort extends Number implements Comparable<MutableShort>, Mu
|
||||
* @throws NumberFormatException 转为Short错误
|
||||
*/
|
||||
public MutableShort(final String value) throws NumberFormatException {
|
||||
super();
|
||||
this.value = Short.parseShort(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Node<T> {
|
||||
* @param treeNodeConfig TreeNode配置
|
||||
*/
|
||||
public Tree(TreeNodeConfig treeNodeConfig) {
|
||||
super();
|
||||
this.treeNodeConfig = ObjectUtil.defaultIfNull(
|
||||
treeNodeConfig, TreeNodeConfig.DEFAULT_CONFIG);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.hutool.core.lang.tree;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 树节点 每个属性都可以在{@link TreeNodeConfig}中被重命名<br>
|
||||
@@ -129,4 +130,21 @@ public class TreeNode<T> implements Node<T> {
|
||||
this.extra = extra;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
TreeNode<?> treeNode = (TreeNode<?>) o;
|
||||
return Objects.equals(id, treeNode.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
||||
|
||||
45
hutool-core/src/main/java/cn/hutool/core/map/FuncKeyMap.java
Normal file
45
hutool-core/src/main/java/cn/hutool/core/map/FuncKeyMap.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package cn.hutool.core.map;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 自定义函数Key风格的Map
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @author Looly
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public class FuncKeyMap<K, V> extends CustomKeyMap<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Function<Object, K> keyFunc;
|
||||
|
||||
// ------------------------------------------------------------------------- Constructor start
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param m Map
|
||||
* @param keyFunc 自定义KEY的函数
|
||||
*/
|
||||
public FuncKeyMap(Map<K, V> m, Function<Object, K> keyFunc) {
|
||||
super(m);
|
||||
}
|
||||
// ------------------------------------------------------------------------- Constructor end
|
||||
|
||||
/**
|
||||
* 将Key转为驼峰风格,如果key为字符串的话
|
||||
*
|
||||
* @param key KEY
|
||||
* @return 驼峰Key
|
||||
*/
|
||||
@Override
|
||||
protected Object customKey(Object key) {
|
||||
if (null != this.keyFunc) {
|
||||
return keyFunc.apply(key);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
116
hutool-core/src/main/java/cn/hutool/core/text/StrMatcher.java
Normal file
116
hutool-core/src/main/java/cn/hutool/core/text/StrMatcher.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package cn.hutool.core.text;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 字符串模式匹配,使用${XXXXX}作为变量,例如:
|
||||
*
|
||||
* <pre>
|
||||
* pattern: ${name}-${age}-${gender}-${country}-${province}-${city}-${status}
|
||||
* text: "小明-19-男-中国-河南-郑州-已婚"
|
||||
* result: {name=小明, age=19, gender=男, country=中国, province=河南, city=郑州, status=已婚}
|
||||
* </pre>
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public class StrMatcher {
|
||||
|
||||
List<String> patterns;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param pattern 模式,变量用${XXX}占位
|
||||
*/
|
||||
public StrMatcher(String pattern) {
|
||||
this.patterns = parse(pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配并提取匹配到的内容
|
||||
* @param text 被匹配的文本
|
||||
* @return 匹配的map,key为变量名,value为匹配到的值
|
||||
*/
|
||||
public Map<String, String> match(String text) {
|
||||
final HashMap<String, String> result = MapUtil.newHashMap(true);
|
||||
int from = 0;
|
||||
String key = null;
|
||||
int to;
|
||||
for (String part : patterns) {
|
||||
if (StrUtil.isWrap(part, "${", "}")) {
|
||||
// 变量
|
||||
key = StrUtil.sub(part, 2, part.length() - 1);
|
||||
} else {
|
||||
to = text.indexOf(part, from);
|
||||
if(to < 0){
|
||||
//普通字符串未匹配到,说明整个模式不能匹配,返回空
|
||||
return MapUtil.empty();
|
||||
}
|
||||
if (null != key && to > from) {
|
||||
// 变量对应部分有内容
|
||||
result.put(key, text.substring(from, to));
|
||||
}
|
||||
// 下一个起始点是普通字符串的末尾
|
||||
from = to + part.length();
|
||||
key = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (null != key && from < text.length()) {
|
||||
// 变量对应部分有内容
|
||||
result.put(key, text.substring(from));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析表达式
|
||||
* @param pattern 表达式,使用${XXXX}作为变量占位符
|
||||
* @return 表达式
|
||||
*/
|
||||
private static List<String> parse(String pattern) {
|
||||
List<String> patterns = new ArrayList<>();
|
||||
final int length = pattern.length();
|
||||
char c = 0;
|
||||
char pre;
|
||||
boolean inVar = false;
|
||||
StrBuilder part = StrUtil.strBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
pre = c;
|
||||
c = pattern.charAt(i);
|
||||
if (inVar) {
|
||||
part.append(c);
|
||||
if ('}' == c) {
|
||||
// 变量结束
|
||||
inVar = false;
|
||||
patterns.add(part.toString());
|
||||
part.clear();
|
||||
}
|
||||
} else if ('{' == c && '$' == pre) {
|
||||
// 变量开始
|
||||
inVar = true;
|
||||
final String preText = part.subString(0, part.length() - 1);
|
||||
if (StrUtil.isNotEmpty(preText)) {
|
||||
patterns.add(preText);
|
||||
}
|
||||
part.reset().append(pre).append(c);
|
||||
} else {
|
||||
// 普通字符
|
||||
part.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (part.length() > 0) {
|
||||
patterns.add(part.toString());
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
}
|
||||
@@ -200,7 +200,7 @@ public class ExecutorBuilder implements Builder<ThreadPoolExecutor> {
|
||||
/**
|
||||
* 创建ExecutorBuilder,开始构建
|
||||
*
|
||||
* @return {@link ExecutorBuilder}
|
||||
* @return this
|
||||
*/
|
||||
public static ExecutorBuilder create() {
|
||||
return new ExecutorBuilder();
|
||||
@@ -227,7 +227,7 @@ public class ExecutorBuilder implements Builder<ThreadPoolExecutor> {
|
||||
/**
|
||||
* 构建ThreadPoolExecutor
|
||||
*
|
||||
* @param builder {@link ExecutorBuilder}
|
||||
* @param builder this
|
||||
* @return {@link ThreadPoolExecutor}
|
||||
*/
|
||||
private static ThreadPoolExecutor build(ExecutorBuilder builder) {
|
||||
|
||||
@@ -294,7 +294,7 @@ public class ClassUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定Public方法 如果找不到对应的方法或方法不为public的则返回<code>null</code>
|
||||
* 查找指定Public方法 如果找不到对应的方法或方法不为public的则返回{@code null}
|
||||
*
|
||||
* @param clazz 类
|
||||
* @param methodName 方法名
|
||||
@@ -341,7 +341,7 @@ public class ClassUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定类中的所有方法(包括非public方法),也包括父类和Object类的方法 找不到方法会返回<code>null</code>
|
||||
* 查找指定类中的所有方法(包括非public方法),也包括父类和Object类的方法 找不到方法会返回{@code null}
|
||||
*
|
||||
* @param clazz 被查找的类
|
||||
* @param methodName 方法名
|
||||
@@ -356,7 +356,7 @@ public class ClassUtil {
|
||||
// ----------------------------------------------------------------------------------------- Field
|
||||
|
||||
/**
|
||||
* 查找指定类中的所有字段(包括非public字段), 字段不存在则返回<code>null</code>
|
||||
* 查找指定类中的所有字段(包括非public字段), 字段不存在则返回{@code null}
|
||||
*
|
||||
* @param clazz 被查找字段的类
|
||||
* @param fieldName 字段名
|
||||
@@ -558,7 +558,7 @@ public class ClassUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较判断types1和types2两组类,如果types1中所有的类都与types2对应位置的类相同,或者是其父类或接口,则返回<code>true</code>
|
||||
* 比较判断types1和types2两组类,如果types1中所有的类都与types2对应位置的类相同,或者是其父类或接口,则返回{@code true}
|
||||
*
|
||||
* @param types1 类组1
|
||||
* @param types2 类组2
|
||||
@@ -626,7 +626,7 @@ public class ClassUtil {
|
||||
* 非单例模式,如果是非静态方法,每次创建一个新对象
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @param classNameWithMethodName 类名和方法名表达式,类名与方法名用<code>.</code>或<code>#</code>连接 例如:com.xiaoleilu.hutool.StrUtil.isEmpty 或 com.xiaoleilu.hutool.StrUtil#isEmpty
|
||||
* @param classNameWithMethodName 类名和方法名表达式,类名与方法名用{@code .}或{@code #}连接 例如:com.xiaoleilu.hutool.StrUtil.isEmpty 或 com.xiaoleilu.hutool.StrUtil#isEmpty
|
||||
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
||||
* @return 返回结果
|
||||
*/
|
||||
@@ -1092,4 +1092,4 @@ public class ClassUtil {
|
||||
}
|
||||
return location.getPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class HexUtil {
|
||||
|
||||
/**
|
||||
* 判断给定字符串是否为16进制数<br>
|
||||
* 如果是,需要使用对应数字类型对象的<code>decode</code>方法解码<br>
|
||||
* 如果是,需要使用对应数字类型对象的{@code decode}方法解码<br>
|
||||
* 例如:{@code Integer.decode}方法解码int类型的16进制数字
|
||||
*
|
||||
* @param value 值
|
||||
@@ -74,7 +74,7 @@ public class HexUtil {
|
||||
* 将字节数组转换为十六进制字符数组
|
||||
*
|
||||
* @param data byte[]
|
||||
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
|
||||
* @param toLowerCase {@code true} 传换成小写格式 , {@code false} 传换成大写格式
|
||||
* @return 十六进制char[]
|
||||
*/
|
||||
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
|
||||
@@ -116,7 +116,7 @@ public class HexUtil {
|
||||
* 将字节数组转换为十六进制字符串
|
||||
*
|
||||
* @param data byte[]
|
||||
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
|
||||
* @param toLowerCase {@code true} 传换成小写格式 , {@code false} 传换成大写格式
|
||||
* @return 十六进制String
|
||||
*/
|
||||
public static String encodeHexStr(byte[] data, boolean toLowerCase) {
|
||||
@@ -421,4 +421,4 @@ public class HexUtil {
|
||||
return digit;
|
||||
}
|
||||
// ---------------------------------------------------------------------------------------- Private method end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1428,10 +1428,62 @@ public class NumberUtil {
|
||||
|
||||
// ------------------------------------------------------------------------------------------- others
|
||||
|
||||
/**
|
||||
* 计算阶乘
|
||||
* <p>
|
||||
* n! = n * (n-1) * ... * 2 * 1
|
||||
* </p>
|
||||
*
|
||||
* @param n 阶乘起始
|
||||
* @return 结果
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static BigInteger factorial(BigInteger n) {
|
||||
if(n.equals(BigInteger.ZERO)){
|
||||
return BigInteger.ONE;
|
||||
}
|
||||
return factorial(n, BigInteger.ZERO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算范围阶乘
|
||||
* <p>
|
||||
* factorial(start, end) = start * (start - 1) * ... * (end - 1)
|
||||
* factorial(start, end) = start * (start - 1) * ... * (end + 1)
|
||||
* </p>
|
||||
*
|
||||
* @param start 阶乘起始(包含)
|
||||
* @param end 阶乘结束,必须小于起始(不包括)
|
||||
* @return 结果
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static BigInteger factorial(BigInteger start, BigInteger end) {
|
||||
Assert.notNull(start, "Factorial start must be not null!");
|
||||
Assert.notNull(end, "Factorial end must be not null!");
|
||||
if(start.compareTo(BigInteger.ZERO) < 0 || end.compareTo(BigInteger.ZERO) < 0){
|
||||
throw new IllegalArgumentException(StrUtil.format("Factorial start and end both must be > 0, but got start={}, end={}", start, end));
|
||||
}
|
||||
|
||||
if (start.equals(BigInteger.ZERO)){
|
||||
start = BigInteger.ONE;
|
||||
}
|
||||
|
||||
if(end.compareTo(BigInteger.ONE) < 0){
|
||||
end = BigInteger.ONE;
|
||||
}
|
||||
|
||||
BigInteger result = start;
|
||||
end = end.add(BigInteger.ONE);
|
||||
while(start.compareTo(end) > 0) {
|
||||
start = start.subtract(BigInteger.ONE);
|
||||
result = result.multiply(start);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算范围阶乘
|
||||
* <p>
|
||||
* factorial(start, end) = start * (start - 1) * ... * (end + 1)
|
||||
* </p>
|
||||
*
|
||||
* @param start 阶乘起始(包含)
|
||||
|
||||
@@ -3,8 +3,6 @@ package cn.hutool.core.util;
|
||||
import cn.hutool.core.lang.PatternPool;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* 手机号工具类
|
||||
|
||||
@@ -3,8 +3,6 @@ package cn.hutool.core.codec;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import cn.hutool.core.codec.BCD;
|
||||
|
||||
public class BCDTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -694,4 +695,14 @@ public class CollUtilTest {
|
||||
|
||||
Assert.assertEquals(0, CollUtil.page(3, 5, objects).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subtractToListTest(){
|
||||
List<Long> list1 = Arrays.asList(1L, 2L, 3L);
|
||||
List<Long> list2 = Arrays.asList(2L, 3L);
|
||||
|
||||
List<Long> result = CollUtil.subtractToList(list1, list2);
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertEquals(1L, result.get(0), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,4 +101,15 @@ public class ListUtilTest {
|
||||
int[] d1 = ListUtil.page(0,8,a).stream().mapToInt(Integer::valueOf).toArray();
|
||||
Assert.assertArrayEquals(new int[]{1,2,3,4,5},d1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subTest(){
|
||||
final List<Integer> of = ListUtil.of(1, 2, 3, 4);
|
||||
final List<Integer> sub = ListUtil.sub(of, 2, 4);
|
||||
sub.remove(0);
|
||||
|
||||
// 对子列表操作不影响原列表
|
||||
Assert.assertEquals(4, of.size());
|
||||
Assert.assertEquals(1, sub.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,9 +3,6 @@ package cn.hutool.core.convert;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import cn.hutool.core.convert.Converter;
|
||||
import cn.hutool.core.convert.ConverterRegistry;
|
||||
|
||||
/**
|
||||
* ConverterRegistry 单元测试
|
||||
* @author Looly
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NumberWordFormatTest {
|
||||
|
||||
@Test
|
||||
public void formatTest() {
|
||||
String format = NumberWordFormatter.format(100.23);
|
||||
Assert.assertEquals("ONE HUNDRED AND CENTS TWENTY THREE ONLY", format);
|
||||
|
||||
String format2 = NumberWordFormatter.format("2100.00");
|
||||
Assert.assertEquals("TWO THOUSAND ONE HUNDRED AND CENTS ONLY", format2);
|
||||
|
||||
String format3 = NumberWordFormatter.formatValue(4384324, false);
|
||||
Assert.assertEquals("4.38m", format3);
|
||||
|
||||
String format4 = NumberWordFormatter.formatValue(4384324);
|
||||
Assert.assertEquals("438.43w", format4);
|
||||
|
||||
String format5 = NumberWordFormatter.formatValue(438);
|
||||
Assert.assertEquals("438", format5);
|
||||
}
|
||||
}
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NumberWordFormatTest {
|
||||
|
||||
@Test
|
||||
public void formatTest() {
|
||||
String format = NumberWordFormatter.format(100.23);
|
||||
Assert.assertEquals("ONE HUNDRED AND CENTS TWENTY THREE ONLY", format);
|
||||
|
||||
String format2 = NumberWordFormatter.format("2100.00");
|
||||
Assert.assertEquals("TWO THOUSAND ONE HUNDRED AND CENTS ONLY", format2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatSimpleTest() {
|
||||
String format1 = NumberWordFormatter.formatSimple(1200, false);
|
||||
Assert.assertEquals("1.2k", format1);
|
||||
|
||||
String format2 = NumberWordFormatter.formatSimple(4384324, false);
|
||||
Assert.assertEquals("4.38m", format2);
|
||||
|
||||
String format3 = NumberWordFormatter.formatSimple(4384324, true);
|
||||
Assert.assertEquals("438.43w", format3);
|
||||
|
||||
String format4 = NumberWordFormatter.formatSimple(4384324);
|
||||
Assert.assertEquals("438.43w", format4);
|
||||
|
||||
String format5 = NumberWordFormatter.formatSimple(438);
|
||||
Assert.assertEquals("438", format5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 文件类型判断单元测试
|
||||
@@ -13,19 +16,19 @@ import java.io.File;
|
||||
*
|
||||
*/
|
||||
public class FileTypeUtilTest {
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void fileTypeUtilTest() {
|
||||
File file = FileUtil.file("hutool.jpg");
|
||||
String type = FileTypeUtil.getType(file);
|
||||
Assert.assertEquals("jpg", type);
|
||||
|
||||
|
||||
FileTypeUtil.putFileType("ffd8ffe000104a464946", "new_jpg");
|
||||
String newType = FileTypeUtil.getType(file);
|
||||
Assert.assertEquals("new_jpg", newType);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void emptyTest() {
|
||||
@@ -41,4 +44,16 @@ public class FileTypeUtilTest {
|
||||
String type = FileTypeUtil.getType(file);
|
||||
Console.log(type);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void ofdTest() {
|
||||
File file = FileUtil.file("e:/test.ofd");
|
||||
String hex = IoUtil.readHex28Upper(FileUtil.getInputStream(file));
|
||||
Console.log(hex);
|
||||
String type = FileTypeUtil.getType(file);
|
||||
Console.log(type);
|
||||
Assert.assertEquals("ofd", type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -51,7 +51,13 @@ public class DataSizeUtilTest {
|
||||
|
||||
@Test
|
||||
public void formatTest(){
|
||||
final String format = DataSizeUtil.format(Long.MAX_VALUE);
|
||||
Assert.assertEquals("8,192 EB", format);
|
||||
String format = DataSizeUtil.format(Long.MAX_VALUE);
|
||||
Assert.assertEquals("8 EB", format);
|
||||
|
||||
format = DataSizeUtil.format(1024L * 1024 * 1024 * 1024 * 1024);
|
||||
Assert.assertEquals("1 PB", format);
|
||||
|
||||
format = DataSizeUtil.format(1024L * 1024 * 1024 * 1024);
|
||||
Assert.assertEquals("1 TB", format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package cn.hutool.core.lang;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ClassScanerTest {
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void scanTest() {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.hutool.core.text;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class StrMatcherTest {
|
||||
|
||||
@Test
|
||||
public void matcherTest(){
|
||||
final StrMatcher strMatcher = new StrMatcher("${name}-${age}-${gender}-${country}-${province}-${city}-${status}");
|
||||
final Map<String, String> match = strMatcher.match("小明-19-男-中国-河南-郑州-已婚");
|
||||
Console.log(match);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matcherTest2(){
|
||||
// 当有无匹配项的时候,按照全不匹配对待
|
||||
final StrMatcher strMatcher = new StrMatcher("${name}-${age}-${gender}-${country}-${province}-${city}-${status}");
|
||||
final Map<String, String> match = strMatcher.match("小明-19-男-中国-河南-郑州");
|
||||
Assert.assertEquals(0, match.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matcherTest3(){
|
||||
// 当有无匹配项的时候,按照全不匹配对待
|
||||
final StrMatcher strMatcher = new StrMatcher("${name}经过${year}年");
|
||||
final Map<String, String> match = strMatcher.match("小明经过20年,成长为一个大人。");
|
||||
Console.log(match);
|
||||
Assert.assertEquals("小明", match.get("name"));
|
||||
Assert.assertEquals("20", match.get("year"));
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* {@link IdUtil} 单元测试
|
||||
*
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
@@ -31,12 +31,12 @@ public class IdUtilTest {
|
||||
String randomUUID = IdUtil.randomUUID();
|
||||
Assert.assertEquals(36, randomUUID.length());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void fastUUIDTest() {
|
||||
String simpleUUID = IdUtil.fastSimpleUUID();
|
||||
Assert.assertEquals(32, simpleUUID.length());
|
||||
|
||||
|
||||
String randomUUID = IdUtil.fastUUID();
|
||||
Assert.assertEquals(36, randomUUID.length());
|
||||
}
|
||||
@@ -60,25 +60,26 @@ public class IdUtilTest {
|
||||
}
|
||||
Console.log(timer.interval());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void objectIdTest() {
|
||||
String id = IdUtil.objectId();
|
||||
Assert.assertEquals(24, id.length());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createSnowflakeTest() {
|
||||
Snowflake snowflake = IdUtil.createSnowflake(1, 1);
|
||||
long id = snowflake.nextId();
|
||||
Assert.assertTrue(id > 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void snowflakeBenchTest() {
|
||||
final Set<Long> set = new ConcurrentHashSet<>();
|
||||
final Snowflake snowflake = IdUtil.createSnowflake(1, 1);
|
||||
|
||||
|
||||
//线程数
|
||||
int threadCount = 100;
|
||||
//每个线程生成的ID数
|
||||
@@ -94,7 +95,7 @@ public class IdUtilTest {
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//等待全部线程结束
|
||||
try {
|
||||
latch.await();
|
||||
@@ -103,11 +104,12 @@ public class IdUtilTest {
|
||||
}
|
||||
Assert.assertEquals(threadCount * idCountPerThread, set.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void snowflakeBenchTest2() {
|
||||
final Set<Long> set = new ConcurrentHashSet<>();
|
||||
|
||||
|
||||
//线程数
|
||||
int threadCount = 100;
|
||||
//每个线程生成的ID数
|
||||
@@ -123,7 +125,7 @@ public class IdUtilTest {
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//等待全部线程结束
|
||||
try {
|
||||
latch.await();
|
||||
|
||||
@@ -5,17 +5,18 @@ import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link NumberUtil} 单元测试类
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class NumberUtilTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void addTest() {
|
||||
Float a = 3.15f;
|
||||
@@ -23,7 +24,7 @@ public class NumberUtilTest {
|
||||
double result = NumberUtil.add(a, b).doubleValue();
|
||||
Assert.assertEquals(7.37, result, 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void addTest2() {
|
||||
double a = 3.15f;
|
||||
@@ -31,7 +32,7 @@ public class NumberUtilTest {
|
||||
double result = NumberUtil.add(a, b);
|
||||
Assert.assertEquals(7.37, result, 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void addTest3() {
|
||||
float a = 3.15f;
|
||||
@@ -39,13 +40,13 @@ public class NumberUtilTest {
|
||||
double result = NumberUtil.add(a, b, a, b).doubleValue();
|
||||
Assert.assertEquals(14.74, result, 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void addTest4() {
|
||||
BigDecimal result = NumberUtil.add(new BigDecimal("133"), new BigDecimal("331"));
|
||||
Assert.assertEquals(new BigDecimal("464"), result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isIntegerTest() {
|
||||
Assert.assertTrue(NumberUtil.isInteger("-12"));
|
||||
@@ -54,7 +55,7 @@ public class NumberUtilTest {
|
||||
Assert.assertTrue(NumberUtil.isInteger("0"));
|
||||
Assert.assertFalse(NumberUtil.isInteger("23.4"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isLongTest() {
|
||||
Assert.assertTrue(NumberUtil.isLong("-12"));
|
||||
@@ -63,7 +64,7 @@ public class NumberUtilTest {
|
||||
Assert.assertTrue(NumberUtil.isLong("0"));
|
||||
Assert.assertFalse(NumberUtil.isLong("23.4"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isNumberTest() {
|
||||
Assert.assertTrue(NumberUtil.isNumber("28.55"));
|
||||
@@ -78,7 +79,7 @@ public class NumberUtilTest {
|
||||
double result = NumberUtil.div(0, 1);
|
||||
Assert.assertEquals(0.0, result, 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void roundTest() {
|
||||
|
||||
@@ -93,7 +94,7 @@ public class NumberUtilTest {
|
||||
String round4 = NumberUtil.roundStr("2.675", 2);
|
||||
Assert.assertEquals("2.68", round3);
|
||||
Assert.assertEquals("2.68", round4);
|
||||
|
||||
|
||||
// 四舍六入五成双
|
||||
String round31 = NumberUtil.roundStr(4.245, 2, RoundingMode.HALF_EVEN);
|
||||
String round41 = NumberUtil.roundStr("4.2451", 2, RoundingMode.HALF_EVEN);
|
||||
@@ -105,7 +106,7 @@ public class NumberUtilTest {
|
||||
String round6 = NumberUtil.roundStr("2.6005", 2);
|
||||
Assert.assertEquals("2.60", round5);
|
||||
Assert.assertEquals("2.60", round6);
|
||||
|
||||
|
||||
// 补0
|
||||
String round7 = NumberUtil.roundStr(2.600, 2);
|
||||
String round8 = NumberUtil.roundStr("2.600", 2);
|
||||
@@ -118,7 +119,7 @@ public class NumberUtilTest {
|
||||
String roundStr = NumberUtil.roundStr(2.647, 2);
|
||||
Assert.assertEquals(roundStr, "2.65");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void roundHalfEvenTest() {
|
||||
String roundStr = NumberUtil.roundHalfEven(4.245, 2).toString();
|
||||
@@ -129,7 +130,7 @@ public class NumberUtilTest {
|
||||
Assert.assertEquals(roundStr, "4.25");
|
||||
roundStr = NumberUtil.roundHalfEven(4.2250, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.22");
|
||||
|
||||
|
||||
roundStr = NumberUtil.roundHalfEven(1.2050, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.20");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2150, 2).toString();
|
||||
@@ -159,14 +160,14 @@ public class NumberUtilTest {
|
||||
String format = NumberUtil.decimalFormat(",###", c);
|
||||
Assert.assertEquals("299,792,458", format);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void decimalFormatMoneyTest() {
|
||||
double c = 299792400.543534534;
|
||||
|
||||
|
||||
String format = NumberUtil.decimalFormatMoney(c);
|
||||
Assert.assertEquals("299,792,400.54", format);
|
||||
|
||||
|
||||
double value = 0.5;
|
||||
String money = NumberUtil.decimalFormatMoney(value);
|
||||
Assert.assertEquals("0.50", money);
|
||||
@@ -176,17 +177,17 @@ public class NumberUtilTest {
|
||||
public void equalsTest() {
|
||||
Assert.assertTrue(NumberUtil.equals(new BigDecimal("0.00"), BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void formatPercentTest() {
|
||||
String str = NumberUtil.formatPercent(0.33543545, 2);
|
||||
Assert.assertEquals("33.54%", str);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void toBigDecimalTest() {
|
||||
double a = 3.14;
|
||||
|
||||
|
||||
BigDecimal bigDecimal = NumberUtil.toBigDecimal(a);
|
||||
Assert.assertEquals("3.14", bigDecimal.toString());
|
||||
|
||||
@@ -208,7 +209,7 @@ public class NumberUtilTest {
|
||||
int min = NumberUtil.min(5,4,3,6,1);
|
||||
Assert.assertEquals(1, min);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parseIntTest() {
|
||||
int number = NumberUtil.parseInt("0xFF");
|
||||
@@ -258,7 +259,7 @@ public class NumberUtilTest {
|
||||
Number v2 = NumberUtil.parseNumber("1,482.00D");
|
||||
Assert.assertEquals(1482L, v2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parseLongTest() {
|
||||
long number = NumberUtil.parseLong("0xFF");
|
||||
@@ -303,18 +304,36 @@ public class NumberUtilTest {
|
||||
Assert.assertEquals(120, factorial);
|
||||
factorial = NumberUtil.factorial(5, 1);
|
||||
Assert.assertEquals(120, factorial);
|
||||
|
||||
|
||||
Assert.assertEquals(5, NumberUtil.factorial(5, 4));
|
||||
Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factorialTest2(){
|
||||
long factorial = NumberUtil.factorial(new BigInteger("0")).longValue();
|
||||
Assert.assertEquals(1, factorial);
|
||||
|
||||
Assert.assertEquals(1L, NumberUtil.factorial(new BigInteger("1")).longValue());
|
||||
Assert.assertEquals(1307674368000L, NumberUtil.factorial(new BigInteger("15")).longValue());
|
||||
Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20));
|
||||
|
||||
factorial = NumberUtil.factorial(new BigInteger("5"), new BigInteger("0")).longValue();
|
||||
Assert.assertEquals(120, factorial);
|
||||
factorial = NumberUtil.factorial(new BigInteger("5"), BigInteger.ONE).longValue();
|
||||
Assert.assertEquals(120, factorial);
|
||||
|
||||
Assert.assertEquals(5, NumberUtil.factorial(new BigInteger("5"), new BigInteger("4")).longValue());
|
||||
Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(new BigInteger("20"), BigInteger.ZERO).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulTest(){
|
||||
final BigDecimal mul = NumberUtil.mul(new BigDecimal("10"), null);
|
||||
Assert.assertEquals(BigDecimal.ZERO, mul);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void isPowerOfTwoTest() {
|
||||
Assert.assertFalse(NumberUtil.isPowerOfTwo(-1));
|
||||
|
||||
Reference in New Issue
Block a user