This commit is contained in:
Looly 2023-04-16 10:47:18 +08:00
parent 6f71822ca7
commit b73d7b2e68
2 changed files with 313 additions and 32 deletions

View File

@ -0,0 +1,284 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.map;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.lang.tuple.Triple;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 三值表结构可重复<br>
* 用于提供三种值相互查找操作<br>
* 查找方式为indexOf方式遍历查找数据越多越慢
*
* @param <L> 左值类型
* @param <M> 中值类型
* @param <R> 右值类型
* @author looly
* @since 6.0.0
*/
public class TripleTable<L, M, R> implements Serializable {
private static final long serialVersionUID = 1L;
private final List<L> lList;
private final List<M> mList;
private final List<R> rList;
/**
* 构造
*
* @param triples 三元组列表
*/
public TripleTable(final List<Triple<L, M, R>> triples) {
this(Assert.notNull(triples).size());
for (final Triple<L, M, R> triple : triples) {
put(triple.getLeft(), triple.getMiddle(), triple.getRight());
}
}
/**
* 构造
*
* @param size 初始容量
*/
public TripleTable(final int size) {
this(new ArrayList<>(size), new ArrayList<>(size), new ArrayList<>(size));
}
/**
* @param lList 左列表
* @param mList 中列表
* @param rList 右列表
*/
public TripleTable(final List<L> lList, final List<M> mList, final List<R> rList) {
Assert.notNull(lList);
Assert.notNull(mList);
Assert.notNull(rList);
final int size = lList.size();
if (size != mList.size() || size != rList.size()) {
throw new IllegalArgumentException("List size must be equals!");
}
this.lList = lList;
this.mList = mList;
this.rList = rList;
}
// region ----- getLeft
/**
* 通过中间值查找左边值<br>
* 如果有多个重复值只返回找到的第一个值
*
* @param mValue 中间值
* @return 左边值未找到返回{@code null}
*/
public L getLeftByMiddle(final M mValue) {
final int index = this.mList.indexOf(mValue);
if (index > -1) {
return this.lList.get(index);
}
return null;
}
/**
* 通过右值查找左边值<br>
* 如果有多个重复值只返回找到的第一个值
*
* @param rValue 右值
* @return 左边值未找到返回{@code null}
*/
public L getLeftByRight(final R rValue) {
final int index = this.rList.indexOf(rValue);
if (index > -1) {
return this.lList.get(index);
}
return null;
}
// endregion
// region ----- getMiddle
/**
* 通过左值查找中值<br>
* 如果有多个重复值只返回找到的第一个值
*
* @param lValue 左值
* @return 中值未找到返回{@code null}
*/
public M getMiddleByLeft(final L lValue) {
final int index = this.lList.indexOf(lValue);
if (index > -1) {
return this.mList.get(index);
}
return null;
}
/**
* 通过右值查找中值<br>
* 如果有多个重复值只返回找到的第一个值
*
* @param rValue 右值
* @return 中值未找到返回{@code null}
*/
public M getMiddleByRight(final R rValue) {
final int index = this.rList.indexOf(rValue);
if (index > -1) {
return this.mList.get(index);
}
return null;
}
// endregion
// region ----- getRight
/**
* 通过左值查找右值<br>
* 如果有多个重复值只返回找到的第一个值
*
* @param lValue 左值
* @return 右值未找到返回{@code null}
*/
public R getRightByLeft(final L lValue) {
final int index = this.lList.indexOf(lValue);
if (index > -1) {
return this.rList.get(index);
}
return null;
}
/**
* 通过中间值查找右值<br>
* 如果有多个重复值只返回找到的第一个值
*
* @param mValue 中间值
* @return 右值未找到返回{@code null}
*/
public R getRightByMiddle(final M mValue) {
final int index = this.mList.indexOf(mValue);
if (index > -1) {
return this.rList.get(index);
}
return null;
}
// endregion
// region ----- getBy
/**
* 通过左值查找三元组所有值
*
* @param lValue 左值
* @return 三元组所有值
*/
public Triple<L, M, R> getByLeft(final L lValue) {
final int index = this.lList.indexOf(lValue);
if (index > -1) {
return new Triple<>(
lList.get(index),
mList.get(index),
rList.get(index)
);
}
return null;
}
/**
* 通过中值查找三元组所有值
*
* @param mValue 中值
* @return 三元组所有值
*/
public Triple<L, M, R> getByMiddle(final M mValue) {
final int index = this.mList.indexOf(mValue);
if (index > -1) {
return new Triple<>(
lList.get(index),
mList.get(index),
rList.get(index)
);
}
return null;
}
/**
* 通过右值查找三元组所有值
*
* @param rValue 右值
* @return 三元组所有值
*/
public Triple<L, M, R> getByRight(final R rValue) {
final int index = this.rList.indexOf(rValue);
if (index > -1) {
return new Triple<>(
lList.get(index),
mList.get(index),
rList.get(index)
);
}
return null;
}
// endregion
/**
* 长度
*
* @return this
*/
public int size() {
return this.lList.size();
}
/**
* 加入值
*
* @param lValue 左值
* @param mValue 中值
* @param rValue 右值
* @return this
*/
public TripleTable<L, M, R> put(final L lValue, final M mValue, final R rValue) {
this.lList.add(lValue);
this.mList.add(mValue);
this.rList.add(rValue);
return this;
}
/**
* 清空
*
* @return this
*/
public TripleTable<L, M, R> clear() {
this.lList.clear();
this.mList.clear();
this.rList.clear();
return this;
}
/**
* 移除值
*
* @param index 序号
* @return this
*/
public TripleTable<L, M, R> remove(final int index) {
this.lList.remove(index);
this.mList.remove(index);
this.rList.remove(index);
return this;
}
}

View File

@ -14,7 +14,7 @@ package org.dromara.hutool.core.reflect;
import org.dromara.hutool.core.exceptions.UtilException;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.map.BiMap;
import org.dromara.hutool.core.map.TripleTable;
import org.dromara.hutool.core.text.StrTrimer;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.CharUtil;
@ -24,7 +24,6 @@ import java.lang.reflect.Method;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.HashMap;
/**
* 类描述工具类<br>
@ -48,6 +47,8 @@ import java.util.HashMap;
* @since 6.0.0
*/
public class ClassDescUtil {
// region ----- const
/**
* void(V).
*/
@ -92,32 +93,28 @@ public class ClassDescUtil {
* short(S).
*/
public static final char JVM_SHORT = 'S';
// endregion
/**
* 原始类型名和其class对应表例如int.class = int
* 9种原始类型对应表<br>
* <pre>
* 原始类型
* 原始类型描述符
* 原始类型名称
* </pre>
*/
private static final BiMap<Class<?>, Character> PRIMITIVE_CLASS_DESC_MAP = new BiMap<>(new HashMap<>(9, 1));
private static final BiMap<Class<?>, String> PRIMITIVE_CLASS_NAME_MAP = new BiMap<>(new HashMap<>(9, 1));
private static final TripleTable<Class<?>, Character, String> PRIMITIVE_TABLE = new TripleTable<>(9);
static {
PRIMITIVE_CLASS_DESC_MAP.put(void.class, JVM_VOID);
PRIMITIVE_CLASS_NAME_MAP.put(void.class, "void");
PRIMITIVE_CLASS_DESC_MAP.put(boolean.class, JVM_BOOLEAN);
PRIMITIVE_CLASS_NAME_MAP.put(boolean.class, "boolean");
PRIMITIVE_CLASS_DESC_MAP.put(byte.class, JVM_BYTE);
PRIMITIVE_CLASS_NAME_MAP.put(byte.class, "byte");
PRIMITIVE_CLASS_DESC_MAP.put(char.class, JVM_CHAR);
PRIMITIVE_CLASS_NAME_MAP.put(char.class, "char");
PRIMITIVE_CLASS_DESC_MAP.put(double.class, JVM_DOUBLE);
PRIMITIVE_CLASS_NAME_MAP.put(double.class, "double");
PRIMITIVE_CLASS_DESC_MAP.put(float.class, JVM_FLOAT);
PRIMITIVE_CLASS_NAME_MAP.put(float.class, "float");
PRIMITIVE_CLASS_DESC_MAP.put(int.class, JVM_INT);
PRIMITIVE_CLASS_NAME_MAP.put(int.class, "int");
PRIMITIVE_CLASS_DESC_MAP.put(long.class, JVM_LONG);
PRIMITIVE_CLASS_NAME_MAP.put(long.class, "long");
PRIMITIVE_CLASS_DESC_MAP.put(short.class, JVM_SHORT);
PRIMITIVE_CLASS_NAME_MAP.put(short.class, "short");
PRIMITIVE_TABLE.put(void.class, JVM_VOID, "void");
PRIMITIVE_TABLE.put(boolean.class, JVM_BOOLEAN, "boolean");
PRIMITIVE_TABLE.put(byte.class, JVM_BYTE, "byte");
PRIMITIVE_TABLE.put(char.class, JVM_CHAR, "char");
PRIMITIVE_TABLE.put(double.class, JVM_DOUBLE, "double");
PRIMITIVE_TABLE.put(float.class, JVM_FLOAT, "float");
PRIMITIVE_TABLE.put(int.class, JVM_INT, "int");
PRIMITIVE_TABLE.put(long.class, JVM_LONG, "long");
PRIMITIVE_TABLE.put(short.class, JVM_SHORT, "short");
}
/**
@ -151,7 +148,7 @@ public class ClassDescUtil {
public static Class<?> descToClass(String desc, final boolean isInitialized, final ClassLoader cl) throws UtilException {
Assert.notNull(desc, "Name must not be null");
final char firstChar = desc.charAt(0);
final Class<?> clazz = PRIMITIVE_CLASS_DESC_MAP.getKey(firstChar);
final Class<?> clazz = PRIMITIVE_TABLE.getLeftByMiddle(firstChar);
if (null != clazz) {
return clazz;
}
@ -188,7 +185,7 @@ public class ClassDescUtil {
}
if (c.isPrimitive()) {
final Character desc = PRIMITIVE_CLASS_DESC_MAP.get(c);
final Character desc = PRIMITIVE_TABLE.getMiddleByLeft(c);
if (null != desc) {
ret.append(desc.charValue());
}
@ -331,10 +328,10 @@ public class ClassDescUtil {
sb.append('[');
}
final Class<?> clazz = PRIMITIVE_CLASS_NAME_MAP.getKey(name);
final Class<?> clazz = PRIMITIVE_TABLE.getLeftByRight(name);
if (null != clazz) {
// 原始类型数组根据name获取其描述
sb.append(PRIMITIVE_CLASS_DESC_MAP.get(clazz).charValue());
sb.append(PRIMITIVE_TABLE.getMiddleByLeft(clazz).charValue());
} else {
// 对象数组必须转换为desc形式
// "java.lang.Object" ==> "Ljava.lang.Object;"
@ -342,7 +339,7 @@ public class ClassDescUtil {
}
name = sb.toString();
} else {
final Class<?> clazz = PRIMITIVE_CLASS_NAME_MAP.getKey(name);
final Class<?> clazz = PRIMITIVE_TABLE.getLeftByRight(name);
if (null != clazz) {
return clazz;
}
@ -373,10 +370,10 @@ public class ClassDescUtil {
sb.append('[');
}
final Class<?> clazz = PRIMITIVE_CLASS_NAME_MAP.getKey(name);
final Class<?> clazz = PRIMITIVE_TABLE.getLeftByRight(name);
if (null != clazz) {
// 原始类型数组根据name获取其描述
sb.append(PRIMITIVE_CLASS_DESC_MAP.get(clazz).charValue());
sb.append(PRIMITIVE_TABLE.getMiddleByLeft(clazz).charValue());
} else {
// "java.lang.Object" ==> "Ljava.lang.Object;"
sb.append('L').append(name.replace(CharUtil.DOT, CharUtil.SLASH)).append(';');
@ -400,9 +397,9 @@ public class ClassDescUtil {
int c = desc.lastIndexOf('[') + 1;
if (desc.length() == c + 1) {
final char descChar = desc.charAt(c);
final Class<?> clazz = PRIMITIVE_CLASS_DESC_MAP.getKey(descChar);
final Class<?> clazz = PRIMITIVE_TABLE.getLeftByMiddle(descChar);
if (null != clazz) {
sb.append(PRIMITIVE_CLASS_NAME_MAP.get(clazz));
sb.append(PRIMITIVE_TABLE.getRightByLeft(clazz));
} else {
throw new UtilException("Unsupported primitive desc: {}", desc);
}