mirror of
https://gitee.com/dromara/hutool.git
synced 2025-06-28 13:34:09 +08:00
fix comment
This commit is contained in:
parent
052c45537b
commit
0220a1c55e
@ -32,8 +32,17 @@ import java.util.Map;
|
|||||||
public class AnnotationProxy<T extends Annotation> implements Annotation, InvocationHandler, Serializable {
|
public class AnnotationProxy<T extends Annotation> implements Annotation, InvocationHandler, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注解
|
||||||
|
*/
|
||||||
private final T annotation;
|
private final T annotation;
|
||||||
|
/**
|
||||||
|
* 注解类型
|
||||||
|
*/
|
||||||
private final Class<T> type;
|
private final Class<T> type;
|
||||||
|
/**
|
||||||
|
* 注解属性
|
||||||
|
*/
|
||||||
private final Map<String, Object> attributes;
|
private final Map<String, Object> attributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +37,13 @@ import java.util.Map;
|
|||||||
public class DynaBean implements Cloneable, Serializable {
|
public class DynaBean implements Cloneable, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bean类
|
||||||
|
*/
|
||||||
private final Class<?> beanClass;
|
private final Class<?> beanClass;
|
||||||
|
/**
|
||||||
|
* bean对象
|
||||||
|
*/
|
||||||
private Object bean;
|
private Object bean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,13 @@ import org.dromara.hutool.core.util.ObjUtil;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbsCopier<S, T> implements Copier<T> {
|
public abstract class AbsCopier<S, T> implements Copier<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 来源对象
|
||||||
|
*/
|
||||||
protected final S source;
|
protected final S source;
|
||||||
|
/**
|
||||||
|
* 目标对象
|
||||||
|
*/
|
||||||
protected final T target;
|
protected final T target;
|
||||||
/**
|
/**
|
||||||
* 拷贝选项
|
* 拷贝选项
|
||||||
|
@ -46,7 +46,9 @@ public class SimpleCache<K, V> implements Iterable<Map.Entry<K, V>>, Serializabl
|
|||||||
* 池
|
* 池
|
||||||
*/
|
*/
|
||||||
private final Map<Mutable<K>, V> rawMap;
|
private final Map<Mutable<K>, V> rawMap;
|
||||||
// 乐观读写锁
|
/**
|
||||||
|
* 乐观读写锁
|
||||||
|
*/
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
/**
|
/**
|
||||||
* 写的时候每个key一把锁,降低锁的粒度
|
* 写的时候每个key一把锁,降低锁的粒度
|
||||||
|
@ -42,6 +42,9 @@ import java.util.stream.Collectors;
|
|||||||
public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存Map
|
||||||
|
*/
|
||||||
protected Map<Mutable<K>, CacheObj<K, V>> cacheMap;
|
protected Map<Mutable<K>, CacheObj<K, V>> cacheMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,13 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
public class CacheObj<K, V> implements Serializable {
|
public class CacheObj<K, V> implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键
|
||||||
|
*/
|
||||||
protected final K key;
|
protected final K key;
|
||||||
|
/**
|
||||||
|
* 值对象
|
||||||
|
*/
|
||||||
protected final V obj;
|
protected final V obj;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +29,9 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
// 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
|
/**
|
||||||
|
* 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
|
||||||
|
*/
|
||||||
protected final ReentrantLock lock = new ReentrantLock();
|
protected final ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,12 +25,14 @@ import java.util.concurrent.locks.StampedLock;
|
|||||||
* @author looly
|
* @author looly
|
||||||
* @since 5.7.15
|
* @since 5.7.15
|
||||||
*/
|
*/
|
||||||
public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
public abstract class StampedCache<K, V> extends AbstractCache<K, V> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
// 乐观锁,此处使用乐观锁解决读多写少的场景
|
/**
|
||||||
// get时乐观读,再检查是否修改,修改则转入悲观读重新读一遍,可以有效解决在写时阻塞大量读操作的情况。
|
* 乐观锁,此处使用乐观锁解决读多写少的场景<br>
|
||||||
// see: https://www.cnblogs.com/jiagoushijuzi/p/13721319.html
|
* get时乐观读,再检查是否修改,修改则转入悲观读重新读一遍,可以有效解决在写时阻塞大量读操作的情况。<br>
|
||||||
|
* see: https://www.cnblogs.com/jiagoushijuzi/p/13721319.html
|
||||||
|
*/
|
||||||
protected final StampedLock lock = new StampedLock();
|
protected final StampedLock lock = new StampedLock();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -163,7 +165,7 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
|||||||
|
|
||||||
// 无效移除
|
// 无效移除
|
||||||
co = removeWithoutLock(key);
|
co = removeWithoutLock(key);
|
||||||
if(isUpdateCount){
|
if (isUpdateCount) {
|
||||||
missCount.increment();
|
missCount.increment();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -22,7 +22,9 @@ import org.dromara.hutool.core.lang.Assert;
|
|||||||
*/
|
*/
|
||||||
public class Caesar {
|
public class Caesar {
|
||||||
|
|
||||||
// 26个字母表
|
/**
|
||||||
|
* 26个字母表
|
||||||
|
*/
|
||||||
public static final String TABLE = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
|
public static final String TABLE = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,6 +47,17 @@ import java.util.stream.LongStream;
|
|||||||
*/
|
*/
|
||||||
public class Hashids implements Encoder<long[], String>, Decoder<String, long[]> {
|
public class Hashids implements Encoder<long[], String>, Decoder<String, long[]> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认编解码字符串
|
||||||
|
*/
|
||||||
|
public static final char[] DEFAULT_ALPHABET = {
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||||
|
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||||
|
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
|
||||||
|
};
|
||||||
|
|
||||||
private static final int LOTTERY_MOD = 100;
|
private static final int LOTTERY_MOD = 100;
|
||||||
private static final double GUARD_THRESHOLD = 12;
|
private static final double GUARD_THRESHOLD = 12;
|
||||||
private static final double SEPARATOR_THRESHOLD = 3.5;
|
private static final double SEPARATOR_THRESHOLD = 3.5;
|
||||||
@ -54,14 +65,6 @@ public class Hashids implements Encoder<long[], String>, Decoder<String, long[]>
|
|||||||
private static final int MIN_ALPHABET_LENGTH = 16;
|
private static final int MIN_ALPHABET_LENGTH = 16;
|
||||||
private static final Pattern HEX_VALUES_PATTERN = Pattern.compile("[\\w\\W]{1,12}");
|
private static final Pattern HEX_VALUES_PATTERN = Pattern.compile("[\\w\\W]{1,12}");
|
||||||
|
|
||||||
// 默认编解码字符串
|
|
||||||
public static final char[] DEFAULT_ALPHABET = {
|
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
|
||||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
|
||||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
|
||||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
|
|
||||||
};
|
|
||||||
// 默认分隔符
|
// 默认分隔符
|
||||||
private static final char[] DEFAULT_SEPARATORS = {
|
private static final char[] DEFAULT_SEPARATORS = {
|
||||||
'c', 'f', 'h', 'i', 's', 't', 'u', 'C', 'F', 'H', 'I', 'S', 'T', 'U'
|
'c', 'f', 'h', 'i', 's', 't', 'u', 'C', 'F', 'H', 'I', 'S', 'T', 'U'
|
||||||
|
@ -26,6 +26,9 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class IterChain<T> implements Iterator<T>, Chain<Iterator<T>, IterChain<T>> {
|
public class IterChain<T> implements Iterator<T>, Chain<Iterator<T>, IterChain<T>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有的Iterator
|
||||||
|
*/
|
||||||
protected final List<Iterator<T>> allIterators = new ArrayList<>();
|
protected final List<Iterator<T>> allIterators = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,6 +71,9 @@ public class IterChain<T> implements Iterator<T>, Chain<Iterator<T>, IterChain<T
|
|||||||
|
|
||||||
// ---------------------------------------------------------------- interface
|
// ---------------------------------------------------------------- interface
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前位置
|
||||||
|
*/
|
||||||
protected int currentIter = -1;
|
protected int currentIter = -1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,7 +29,13 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Partition<T> extends AbstractList<List<T>> {
|
public class Partition<T> extends AbstractList<List<T>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被分区的列表
|
||||||
|
*/
|
||||||
protected final List<T> list;
|
protected final List<T> list;
|
||||||
|
/**
|
||||||
|
* 每个分区的长度
|
||||||
|
*/
|
||||||
protected final int size;
|
protected final int size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,7 +60,7 @@ public class Partition<T> extends AbstractList<List<T>> {
|
|||||||
public int size() {
|
public int size() {
|
||||||
// 此处采用动态计算,以应对list变
|
// 此处采用动态计算,以应对list变
|
||||||
final int size = this.size;
|
final int size = this.size;
|
||||||
if(0 == size){
|
if (0 == size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +21,16 @@ import java.util.function.Predicate;
|
|||||||
* 自定义加入前检查的{@link LinkedBlockingQueue},给定一个检查函数,在加入元素前检查此函数<br>
|
* 自定义加入前检查的{@link LinkedBlockingQueue},给定一个检查函数,在加入元素前检查此函数<br>
|
||||||
* 原理是通过Runtime#freeMemory()获取剩余内存,当剩余内存低于指定的阈值时,不再加入。
|
* 原理是通过Runtime#freeMemory()获取剩余内存,当剩余内存低于指定的阈值时,不再加入。
|
||||||
*
|
*
|
||||||
|
* @param <E> 元素类型
|
||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class CheckedLinkedBlockingQueue<E> extends LinkedBlockingQueue<E> {
|
public class CheckedLinkedBlockingQueue<E> extends LinkedBlockingQueue<E> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查函数
|
||||||
|
*/
|
||||||
protected final Predicate<E> checker;
|
protected final Predicate<E> checker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +46,7 @@ public class CheckedLinkedBlockingQueue<E> extends LinkedBlockingQueue<E> {
|
|||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param c 初始集合
|
* @param c 初始集合
|
||||||
* @param checker 检查函数
|
* @param checker 检查函数
|
||||||
*/
|
*/
|
||||||
public CheckedLinkedBlockingQueue(final Collection<? extends E> c, final Predicate<E> checker) {
|
public CheckedLinkedBlockingQueue(final Collection<? extends E> c, final Predicate<E> checker) {
|
||||||
|
@ -30,7 +30,13 @@ import java.util.Objects;
|
|||||||
public class NullComparator<T> implements Comparator<T>, Serializable {
|
public class NullComparator<T> implements Comparator<T>, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否{@code null}最大,排在最后
|
||||||
|
*/
|
||||||
protected final boolean nullGreater;
|
protected final boolean nullGreater;
|
||||||
|
/**
|
||||||
|
* 实际比较器
|
||||||
|
*/
|
||||||
protected final Comparator<T> comparator;
|
protected final Comparator<T> comparator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,6 +32,9 @@ import java.lang.reflect.Type;
|
|||||||
public class ReferenceConverter extends AbstractConverter {
|
public class ReferenceConverter extends AbstractConverter {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例
|
||||||
|
*/
|
||||||
public static ReferenceConverter INSTANCE = new ReferenceConverter();
|
public static ReferenceConverter INSTANCE = new ReferenceConverter();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -29,18 +29,10 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
* 4. INC 自增计数器。确保同一秒内产生objectId的唯一性。
|
* 4. INC 自增计数器。确保同一秒内产生objectId的唯一性。
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <table summary="" border="1">
|
* <pre>
|
||||||
* <tr>
|
* | 时间戳 | 随机数 | 自增计数器 |
|
||||||
* <td>时间戳</td>
|
* | 4 | 4 | 4 |
|
||||||
* <td>随机数</td>
|
* </pre>
|
||||||
* <td>自增计数器</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>4</td>
|
|
||||||
* <td>4</td>
|
|
||||||
* <td>4</td>
|
|
||||||
* </tr>
|
|
||||||
* </table>
|
|
||||||
* <p>
|
* <p>
|
||||||
* 参考:<a href="https://github.com/mongodb/mongo-java-driver/blob/master/bson/src/main/org/bson/types/ObjectId.java">...</a>
|
* 参考:<a href="https://github.com/mongodb/mongo-java-driver/blob/master/bson/src/main/org/bson/types/ObjectId.java">...</a>
|
||||||
*
|
*
|
||||||
|
@ -46,7 +46,9 @@ public class SeataSnowflake implements Generator<Long>, Serializable {
|
|||||||
|
|
||||||
// 节点ID长度
|
// 节点ID长度
|
||||||
private static final int NODE_ID_BITS = 10;
|
private static final int NODE_ID_BITS = 10;
|
||||||
// 节点ID的最大值,1023
|
/**
|
||||||
|
* 节点ID的最大值,1023
|
||||||
|
*/
|
||||||
protected static final int MAX_NODE_ID = ~(-1 << NODE_ID_BITS);
|
protected static final int MAX_NODE_ID = ~(-1 << NODE_ID_BITS);
|
||||||
// 时间戳长度
|
// 时间戳长度
|
||||||
private static final int TIMESTAMP_BITS = 41;
|
private static final int TIMESTAMP_BITS = 41;
|
||||||
|
@ -53,10 +53,14 @@ public class Snowflake implements Generator<Long>, Serializable {
|
|||||||
*/
|
*/
|
||||||
public static final long DEFAULT_TWEPOCH = 1288834974657L;
|
public static final long DEFAULT_TWEPOCH = 1288834974657L;
|
||||||
private static final long WORKER_ID_BITS = 5L;
|
private static final long WORKER_ID_BITS = 5L;
|
||||||
// 最大支持机器节点数0~31,一共32个
|
/**
|
||||||
|
* 最大支持机器节点数0~31,一共32个
|
||||||
|
*/
|
||||||
protected static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
|
protected static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
|
||||||
private static final long DATA_CENTER_ID_BITS = 5L;
|
private static final long DATA_CENTER_ID_BITS = 5L;
|
||||||
// 最大支持数据中心节点数0~31,一共32个
|
/**
|
||||||
|
* 最大支持数据中心节点数0~31,一共32个
|
||||||
|
*/
|
||||||
protected static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
|
protected static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
|
||||||
// 序列号12位(表示只允许序号的范围为:0-4095)
|
// 序列号12位(表示只允许序号的范围为:0-4095)
|
||||||
private static final long SEQUENCE_BITS = 12L;
|
private static final long SEQUENCE_BITS = 12L;
|
||||||
|
@ -26,6 +26,9 @@ import java.nio.CharBuffer;
|
|||||||
*/
|
*/
|
||||||
public class ReaderWrapper extends Reader implements Wrapper<Reader> {
|
public class ReaderWrapper extends Reader implements Wrapper<Reader> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原始Reader
|
||||||
|
*/
|
||||||
protected final Reader raw;
|
protected final Reader raw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +29,9 @@ public class CRC16 implements Checksum, Serializable {
|
|||||||
|
|
||||||
private final CRC16Checksum crc16;
|
private final CRC16Checksum crc16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
public CRC16() {
|
public CRC16() {
|
||||||
this(new CRC16IBM());
|
this(new CRC16IBM());
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ public abstract class CRC16Checksum implements Checksum, Serializable {
|
|||||||
*/
|
*/
|
||||||
protected int wCRCin;
|
protected int wCRCin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
public CRC16Checksum(){
|
public CRC16Checksum(){
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ import org.dromara.hutool.core.io.StreamProgress;
|
|||||||
*/
|
*/
|
||||||
public abstract class IoCopier<S, T> {
|
public abstract class IoCopier<S, T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存大小
|
||||||
|
*/
|
||||||
protected final int bufferSize;
|
protected final int bufferSize;
|
||||||
/**
|
/**
|
||||||
* 拷贝总数
|
* 拷贝总数
|
||||||
|
@ -30,7 +30,13 @@ import java.nio.charset.StandardCharsets;
|
|||||||
public class FileWrapper implements Wrapper<File>, Serializable {
|
public class FileWrapper implements Wrapper<File>, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被包装的文件
|
||||||
|
*/
|
||||||
protected File file;
|
protected File file;
|
||||||
|
/**
|
||||||
|
* 编码
|
||||||
|
*/
|
||||||
protected Charset charset;
|
protected Charset charset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,26 +21,43 @@ package org.dromara.hutool.core.io.file;
|
|||||||
* Windows系统换行符:"\r\n"
|
* Windows系统换行符:"\r\n"
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* @author Looly
|
||||||
* @see #MAC
|
* @see #MAC
|
||||||
* @see #LINUX
|
* @see #LINUX
|
||||||
* @see #WINDOWS
|
* @see #WINDOWS
|
||||||
* @author Looly
|
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
*/
|
*/
|
||||||
public enum LineSeparator {
|
public enum LineSeparator {
|
||||||
/** Mac系统换行符:"\r" */
|
|
||||||
|
/**
|
||||||
|
* Mac系统换行符:"\r"
|
||||||
|
*/
|
||||||
MAC("\r"),
|
MAC("\r"),
|
||||||
/** Linux系统换行符:"\n" */
|
/**
|
||||||
|
* Linux系统换行符:"\n"
|
||||||
|
*/
|
||||||
LINUX("\n"),
|
LINUX("\n"),
|
||||||
/** Windows系统换行符:"\r\n" */
|
/**
|
||||||
|
* Windows系统换行符:"\r\n"
|
||||||
|
*/
|
||||||
WINDOWS("\r\n");
|
WINDOWS("\r\n");
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param lineSeparator 换行符
|
||||||
|
*/
|
||||||
LineSeparator(final String lineSeparator) {
|
LineSeparator(final String lineSeparator) {
|
||||||
this.value = lineSeparator;
|
this.value = lineSeparator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取换行符值
|
||||||
|
*
|
||||||
|
* @return 值
|
||||||
|
*/
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,15 @@ import java.net.URL;
|
|||||||
public class UrlResource implements Resource, Serializable {
|
public class UrlResource implements Resource, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL
|
||||||
|
*/
|
||||||
protected URL url;
|
protected URL url;
|
||||||
private long lastModified = 0;
|
/**
|
||||||
|
* 资源名称
|
||||||
|
*/
|
||||||
protected String name;
|
protected String name;
|
||||||
|
private long lastModified = 0;
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------- Constructor start
|
//-------------------------------------------------------------------------------------- Constructor start
|
||||||
|
|
||||||
|
@ -56,6 +56,9 @@ public enum DataUnit {
|
|||||||
*/
|
*/
|
||||||
TERABYTES("TB", DataSize.ofTerabytes(1));
|
TERABYTES("TB", DataSize.ofTerabytes(1));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单位名称列表
|
||||||
|
*/
|
||||||
public static final String[] UNIT_NAMES = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};
|
public static final String[] UNIT_NAMES = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};
|
||||||
|
|
||||||
private final String suffix;
|
private final String suffix;
|
||||||
|
@ -12,34 +12,74 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.io.watch;
|
package org.dromara.hutool.core.io.watch;
|
||||||
|
|
||||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
import org.dromara.hutool.core.exception.HutoolException;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监听异常
|
* 监听异常
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class WatchException extends RuntimeException {
|
public class WatchException extends HutoolException {
|
||||||
private static final long serialVersionUID = 8068509879445395353L;
|
private static final long serialVersionUID = 8068509879445395353L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param e 异常
|
||||||
|
*/
|
||||||
public WatchException(final Throwable e) {
|
public WatchException(final Throwable e) {
|
||||||
super(ExceptionUtil.getMessage(e), e);
|
super(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
*/
|
||||||
public WatchException(final String message) {
|
public WatchException(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param messageTemplate 消息模板
|
||||||
|
* @param params 参数
|
||||||
|
*/
|
||||||
public WatchException(final String messageTemplate, final Object... params) {
|
public WatchException(final String messageTemplate, final Object... params) {
|
||||||
super(StrUtil.format(messageTemplate, params));
|
super(messageTemplate, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WatchException(final String message, final Throwable throwable) {
|
/**
|
||||||
super(message, throwable);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
*/
|
||||||
|
public WatchException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WatchException(final Throwable throwable, final String messageTemplate, final Object... params) {
|
/**
|
||||||
super(StrUtil.format(messageTemplate, params), throwable);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
* @param enableSuppression 是否启用抑制
|
||||||
|
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
||||||
|
*/
|
||||||
|
public WatchException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
* @param messageTemplate 消息模板
|
||||||
|
* @param params 参数
|
||||||
|
*/
|
||||||
|
public WatchException(final Throwable cause, final String messageTemplate, final Object... params) {
|
||||||
|
super(cause, messageTemplate, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,13 @@ public class MutableEntry<K, V> extends AbsEntry<K, V> implements Mutable<Map.En
|
|||||||
return new MutableEntry<>(key, value);
|
return new MutableEntry<>(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键
|
||||||
|
*/
|
||||||
protected K key;
|
protected K key;
|
||||||
|
/**
|
||||||
|
* 值
|
||||||
|
*/
|
||||||
protected V value;
|
protected V value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +23,13 @@ import org.dromara.hutool.core.text.StrUtil;
|
|||||||
*/
|
*/
|
||||||
public class DefaultSegment<T extends Number> implements Segment<T> {
|
public class DefaultSegment<T extends Number> implements Segment<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 起始位置
|
||||||
|
*/
|
||||||
protected T beginIndex;
|
protected T beginIndex;
|
||||||
|
/**
|
||||||
|
* 结束位置
|
||||||
|
*/
|
||||||
protected T endIndex;
|
protected T endIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +42,13 @@ public class Pair<L, R> implements Serializable, Cloneable {
|
|||||||
return new Pair<>(left, right);
|
return new Pair<>(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 左值(第一个值)
|
||||||
|
*/
|
||||||
protected L left;
|
protected L left;
|
||||||
|
/**
|
||||||
|
* 右值(第二个值)
|
||||||
|
*/
|
||||||
protected R right;
|
protected R right;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,6 +42,9 @@ public class Triple<L, M, R> extends Pair<L, R> {
|
|||||||
return new Triple<>(left, middle, right);
|
return new Triple<>(left, middle, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中值
|
||||||
|
*/
|
||||||
protected M middle;
|
protected M middle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,6 +60,7 @@ public class Triple<L, M, R> extends Pair<L, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- getXXX
|
// region ----- getXXX
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取中值
|
* 获取中值
|
||||||
*
|
*
|
||||||
|
@ -22,6 +22,9 @@ package org.dromara.hutool.core.lang.wrapper;
|
|||||||
*/
|
*/
|
||||||
public class SimpleWrapper<T> implements Wrapper<T> {
|
public class SimpleWrapper<T> implements Wrapper<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原始对象
|
||||||
|
*/
|
||||||
protected final T raw;
|
protected final T raw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,28 +10,10 @@
|
|||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This package contains an implementation of a bounded
|
* 并发Map工具类
|
||||||
* {@link java.util.concurrent.ConcurrentMap} data structure.
|
|
||||||
* <p>
|
|
||||||
* {@link org.dromara.hutool.core.map.concurrent.Weigher} is a simple interface
|
|
||||||
* for determining how many units of capacity an entry consumes. Depending on
|
|
||||||
* which concrete Weigher class is used, an entry may consume a different amount
|
|
||||||
* of space within the cache. The
|
|
||||||
* {@link org.dromara.hutool.core.map.concurrent.Weighers} class provides
|
|
||||||
* utility methods for obtaining the most common kinds of implementations.
|
|
||||||
* <p>
|
|
||||||
* {@link org.dromara.hutool.core.map.concurrent.ConcurrentLinkedHashMap#listener} provides the
|
|
||||||
* ability to be notified when an entry is evicted from the map. An eviction
|
|
||||||
* occurs when the entry was automatically removed due to the map exceeding a
|
|
||||||
* capacity threshold. It is not called when an entry was explicitly removed.
|
|
||||||
* <p>
|
|
||||||
* The {@link org.dromara.hutool.core.map.concurrent.ConcurrentLinkedHashMap}
|
|
||||||
* class supplies an efficient, scalable, thread-safe, bounded map. As with the
|
|
||||||
* <tt>Java Collections Framework</tt> the "Concurrent" prefix is used to
|
|
||||||
* indicate that the map is not governed by a single exclusion lock.
|
|
||||||
*
|
*
|
||||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
* @author Looly
|
||||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
|
||||||
*/
|
*/
|
||||||
package org.dromara.hutool.core.map.concurrent;
|
package org.dromara.hutool.core.map.concurrent;
|
||||||
|
@ -158,8 +158,8 @@ public class NumberValidator {
|
|||||||
*
|
*
|
||||||
* @param s 校验的字符串, 只能含有 正负号、数字字符 和 {@literal X/x}
|
* @param s 校验的字符串, 只能含有 正负号、数字字符 和 {@literal X/x}
|
||||||
* @return 是否为 {@link Integer}类型
|
* @return 是否为 {@link Integer}类型
|
||||||
* @apiNote 6.0.0 支持8进制和16进制
|
|
||||||
* @see Integer#decode(String)
|
* @see Integer#decode(String)
|
||||||
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public static boolean isInteger(final String s) {
|
public static boolean isInteger(final String s) {
|
||||||
if (!isNumber(s)) {
|
if (!isNumber(s)) {
|
||||||
@ -185,7 +185,7 @@ public class NumberValidator {
|
|||||||
*
|
*
|
||||||
* @param s 校验的字符串, 只能含有 正负号、数字字符、{@literal X/x} 和 后缀{@literal L/l}
|
* @param s 校验的字符串, 只能含有 正负号、数字字符、{@literal X/x} 和 后缀{@literal L/l}
|
||||||
* @return 是否为 {@link Long}类型
|
* @return 是否为 {@link Long}类型
|
||||||
* @apiNote 6.0.0 支持8进制和16进制数字
|
* @since 6.0.0
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public static boolean isLong(final String s) {
|
public static boolean isLong(final String s) {
|
||||||
|
@ -104,6 +104,9 @@ public class MultipartRequestInputStream extends BufferedInputStream {
|
|||||||
|
|
||||||
// ---------------------------------------------------------------- data header
|
// ---------------------------------------------------------------- data header
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后的头部信息
|
||||||
|
*/
|
||||||
protected UploadFileHeader lastHeader;
|
protected UploadFileHeader lastHeader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,9 +31,6 @@ public class UploadSetting {
|
|||||||
/** 扩展名是允许列表还是禁止列表 */
|
/** 扩展名是允许列表还是禁止列表 */
|
||||||
protected boolean isAllowFileExts = true;
|
protected boolean isAllowFileExts = true;
|
||||||
|
|
||||||
public UploadSetting() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------- Setters and Getters start
|
// ---------------------------------------------------------------------- Setters and Getters start
|
||||||
/**
|
/**
|
||||||
* @return 获得最大文件大小,-1表示无限制
|
* @return 获得最大文件大小,-1表示无限制
|
||||||
|
@ -25,16 +25,28 @@ import java.nio.charset.Charset;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbsServiceLoader<S> implements ServiceLoader<S> {
|
public abstract class AbsServiceLoader<S> implements ServiceLoader<S> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径前缀
|
||||||
|
*/
|
||||||
protected final String pathPrefix;
|
protected final String pathPrefix;
|
||||||
|
/**
|
||||||
|
* 服务类
|
||||||
|
*/
|
||||||
protected final Class<S> serviceClass;
|
protected final Class<S> serviceClass;
|
||||||
|
/**
|
||||||
|
* 自定义类加载器
|
||||||
|
*/
|
||||||
protected final ClassLoader classLoader;
|
protected final ClassLoader classLoader;
|
||||||
|
/**
|
||||||
|
* 编码
|
||||||
|
*/
|
||||||
protected final Charset charset;
|
protected final Charset charset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param pathPrefix 路径前缀
|
* @param pathPrefix 路径前缀
|
||||||
* @param serviceClass 服务名称
|
* @param serviceClass 服务类
|
||||||
* @param classLoader 自定义类加载器, {@code null}表示使用默认当前的类加载器
|
* @param classLoader 自定义类加载器, {@code null}表示使用默认当前的类加载器
|
||||||
* @param charset 编码,默认UTF-8
|
* @param charset 编码,默认UTF-8
|
||||||
*/
|
*/
|
||||||
|
@ -471,17 +471,17 @@ public class EasyStream<T> extends AbstractEnhancedWrappedStream<T, EasyStream<T
|
|||||||
public interface Builder<T> extends Consumer<T>, org.dromara.hutool.core.lang.builder.Builder<EasyStream<T>> {
|
public interface Builder<T> extends Consumer<T>, org.dromara.hutool.core.lang.builder.Builder<EasyStream<T>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an element to the unwrap being built.
|
* Adds an element to the unwrap being built.<br>
|
||||||
|
* The default implementation behaves as if:
|
||||||
|
* <pre>{@code
|
||||||
|
* accept(t)
|
||||||
|
* return this;
|
||||||
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param t the element to add
|
* @param t 需要添加的元素
|
||||||
* @return {@code this} builder
|
* @return {@code this} builder
|
||||||
* @throws IllegalStateException if the builder has already transitioned to
|
* @throws IllegalStateException if the builder has already transitioned to
|
||||||
* the built state
|
* the built state
|
||||||
* @implSpec The default implementation behaves as if:
|
|
||||||
* <pre>{@code
|
|
||||||
* accept(t)
|
|
||||||
* return this;
|
|
||||||
* }</pre>
|
|
||||||
*/
|
*/
|
||||||
default Builder<T> add(final T t) {
|
default Builder<T> add(final T t) {
|
||||||
accept(t);
|
accept(t);
|
||||||
|
@ -214,7 +214,7 @@ public class StreamUtil {
|
|||||||
public static <T> Stream<T> iterate(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
public static <T> Stream<T> iterate(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||||
Objects.requireNonNull(next);
|
Objects.requireNonNull(next);
|
||||||
Objects.requireNonNull(hasNext);
|
Objects.requireNonNull(hasNext);
|
||||||
return StreamSupport.stream(IterateSpliterator.create(seed, hasNext, next), false);
|
return StreamSupport.stream(IterateSpliterator.of(seed, hasNext, next), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -305,7 +305,7 @@ public class StreamUtil {
|
|||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
Objects.requireNonNull(predicate);
|
Objects.requireNonNull(predicate);
|
||||||
return createStatefulNewStream(source, DropWhileSpliterator.create(source.spliterator(), predicate));
|
return createStatefulNewStream(source, DropWhileSpliterator.of(source.spliterator(), predicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
// region ----- 私有方法
|
// region ----- 私有方法
|
||||||
|
@ -263,11 +263,7 @@ public interface TransformableWrappedStream<T, S extends TransformableWrappedStr
|
|||||||
// region ============ peek ============
|
// region ============ peek ============
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回与指定函数将元素作为参数执行后组成的流。操作带下标
|
* 返回与指定函数将元素作为参数执行后组成的流。操作带下标,该方法存在的意义主要是用来调试。
|
||||||
*
|
|
||||||
* @param action 指定的函数
|
|
||||||
* @return 返回叠加操作后的FastStream
|
|
||||||
* @apiNote 该方法存在的意义主要是用来调试
|
|
||||||
* 当你需要查看经过操作管道某处的元素和下标,可以执行以下操作:
|
* 当你需要查看经过操作管道某处的元素和下标,可以执行以下操作:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* Stream.of("one", "two", "three", "four")
|
* Stream.of("one", "two", "three", "four")
|
||||||
@ -277,6 +273,9 @@ public interface TransformableWrappedStream<T, S extends TransformableWrappedStr
|
|||||||
* .peekIdx((e,i) -> System.out.println("Mapped value: " + e + " Mapped idx:" + i))
|
* .peekIdx((e,i) -> System.out.println("Mapped value: " + e + " Mapped idx:" + i))
|
||||||
* .collect(Collectors.toList());
|
* .collect(Collectors.toList());
|
||||||
* }</pre>
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @param action 指定的函数
|
||||||
|
* @return 返回叠加操作后的FastStream
|
||||||
*/
|
*/
|
||||||
default S peekIdx(final BiConsumer<? super T, Integer> action) {
|
default S peekIdx(final BiConsumer<? super T, Integer> action) {
|
||||||
Objects.requireNonNull(action);
|
Objects.requireNonNull(action);
|
||||||
|
@ -188,21 +188,19 @@ public interface WrappedStream<T, S extends WrappedStream<T, S>> extends Stream<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回与指定函数将元素作为参数执行后组成的流。
|
* 返回与指定函数将元素作为参数执行后组成的流。这是一个无状态中间操作<br>
|
||||||
* 这是一个无状态中间操作
|
* 该方法存在的意义主要是用来调试。当你需要查看经过操作管道某处的元素,可以执行以下操作:
|
||||||
*
|
|
||||||
* @param action 指定的函数
|
|
||||||
* @return 返回叠加操作后的FastStream
|
|
||||||
* @apiNote 该方法存在的意义主要是用来调试
|
|
||||||
* 当你需要查看经过操作管道某处的元素,可以执行以下操作:
|
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* .of("one", "two", "three", "four")
|
* .of("one", "two", "three", "four")
|
||||||
* .filter(e -> e.length() > 3)
|
* .filter(e -> e.length() > 3)
|
||||||
* .peek(e -> System.out.println("Filtered value: " + e))
|
* .peek(e -> Console.log("Filtered value: " + e))
|
||||||
* .map(String::toUpperCase)
|
* .map(String::toUpperCase)
|
||||||
* .peek(e -> System.out.println("Mapped value: " + e))
|
* .peek(e -> Console.log("Mapped value: " + e))
|
||||||
* .collect(Collectors.toList());
|
* .collect(Collectors.toList());
|
||||||
* }</pre>
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @param action 指定的函数
|
||||||
|
* @return 返回叠加操作后的FastStream
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
default S peek(final Consumer<? super T> action) {
|
default S peek(final Consumer<? super T> action) {
|
||||||
|
@ -21,12 +21,21 @@ import java.util.function.Predicate;
|
|||||||
* dropWhile 的 Spliterator
|
* dropWhile 的 Spliterator
|
||||||
* <p>借鉴自StreamEx</p>
|
* <p>借鉴自StreamEx</p>
|
||||||
*
|
*
|
||||||
|
* @param <T> 元素类型
|
||||||
* @author emptypoint
|
* @author emptypoint
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class DropWhileSpliterator<T> implements Spliterator<T> {
|
public class DropWhileSpliterator<T> implements Spliterator<T> {
|
||||||
|
|
||||||
public static <T> DropWhileSpliterator<T> create(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
/**
|
||||||
|
* 创建
|
||||||
|
*
|
||||||
|
* @param source {@link Spliterator}
|
||||||
|
* @param predicate 断言
|
||||||
|
* @param <T> 元素类型
|
||||||
|
* @return DropWhileSpliterator
|
||||||
|
*/
|
||||||
|
public static <T> DropWhileSpliterator<T> of(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
||||||
return new DropWhileSpliterator<>(source, predicate);
|
return new DropWhileSpliterator<>(source, predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +43,13 @@ public class DropWhileSpliterator<T> implements Spliterator<T> {
|
|||||||
private final Predicate<? super T> predicate;
|
private final Predicate<? super T> predicate;
|
||||||
private boolean isFound = false;
|
private boolean isFound = false;
|
||||||
|
|
||||||
private DropWhileSpliterator(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param source {@link Spliterator}
|
||||||
|
* @param predicate 断言
|
||||||
|
*/
|
||||||
|
public DropWhileSpliterator(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.predicate = predicate;
|
this.predicate = predicate;
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,23 @@ import java.util.function.UnaryOperator;
|
|||||||
/**
|
/**
|
||||||
* 无限有序流 的Spliterator
|
* 无限有序流 的Spliterator
|
||||||
*
|
*
|
||||||
|
* @param <T> 流元素类型
|
||||||
* @author VampireAchao
|
* @author VampireAchao
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class IterateSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
|
public class IterateSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param seed 初始值
|
||||||
|
* @param hasNext 是否有下一个断言
|
||||||
|
* @param next 下一个值生产者
|
||||||
|
* @param <T> 流元素类型
|
||||||
|
* @return IterateSpliterator
|
||||||
|
*/
|
||||||
|
public static <T> IterateSpliterator<T> of(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||||
|
return new IterateSpliterator<>(seed, hasNext, next);
|
||||||
|
}
|
||||||
|
|
||||||
private final T seed;
|
private final T seed;
|
||||||
private final Predicate<? super T> hasNext;
|
private final Predicate<? super T> hasNext;
|
||||||
private final UnaryOperator<T> next;
|
private final UnaryOperator<T> next;
|
||||||
@ -34,20 +47,19 @@ public class IterateSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
|
|||||||
private boolean finished;
|
private boolean finished;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a spliterator reporting the given estimated size and
|
* 构造
|
||||||
* additionalCharacteristics.
|
*
|
||||||
|
* @param seed 初始值
|
||||||
|
* @param hasNext 是否有下一个断言
|
||||||
|
* @param next 下一个值生产者
|
||||||
*/
|
*/
|
||||||
IterateSpliterator(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
public IterateSpliterator(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||||
super(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
super(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
||||||
this.seed = seed;
|
this.seed = seed;
|
||||||
this.hasNext = hasNext;
|
this.hasNext = hasNext;
|
||||||
this.next = next;
|
this.next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> IterateSpliterator<T> create(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
|
||||||
return new IterateSpliterator<>(seed, hasNext, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tryAdvance(final Consumer<? super T> action) {
|
public boolean tryAdvance(final Consumer<? super T> action) {
|
||||||
Objects.requireNonNull(action);
|
Objects.requireNonNull(action);
|
||||||
|
@ -437,7 +437,7 @@ public class AntPathMatcher {
|
|||||||
*/
|
*/
|
||||||
protected String[] tokenizePath(final String path) {
|
protected String[] tokenizePath(final String path) {
|
||||||
return SplitUtil.split(path, this.pathSeparator, this.trimTokens, true)
|
return SplitUtil.split(path, this.pathSeparator, this.trimTokens, true)
|
||||||
.toArray(new String[0]);
|
.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -530,7 +530,7 @@ public class AntPathMatcher {
|
|||||||
* 提取参数
|
* 提取参数
|
||||||
*
|
*
|
||||||
* @param pattern 模式
|
* @param pattern 模式
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @return 参数
|
* @return 参数
|
||||||
*/
|
*/
|
||||||
public Map<String, String> extractUriTemplateVariables(final String pattern, final String path) {
|
public Map<String, String> extractUriTemplateVariables(final String pattern, final String path) {
|
||||||
@ -548,22 +548,22 @@ public class AntPathMatcher {
|
|||||||
* the first pattern contains a file extension match (e.g., {@code *.html}).
|
* the first pattern contains a file extension match (e.g., {@code *.html}).
|
||||||
* In that case, the second pattern will be merged into the first. Otherwise,
|
* In that case, the second pattern will be merged into the first. Otherwise,
|
||||||
* an {@code IllegalArgumentException} will be thrown.
|
* an {@code IllegalArgumentException} will be thrown.
|
||||||
* <p>Examples</p>
|
* <table border="1">
|
||||||
* <table border="1" summary="">
|
* <caption>Examples</caption>
|
||||||
* <tr><th>Pattern 1</th><th>Pattern 2</th><th>Result</th></tr>
|
* <tr><th>Pattern 1</th><th>Pattern 2</th><th>Result</th></tr>
|
||||||
* <tr><td>{@code null}</td><td>{@code null}</td><td> </td></tr>
|
* <tr><td>{@code null}</td><td>{@code null}</td><td> </td></tr>
|
||||||
* <tr><td>/hotels</td><td>{@code null}</td><td>/hotels</td></tr>
|
* <tr><td>/hotels</td><td>{@code null}</td><td>/hotels</td></tr>
|
||||||
* <tr><td>{@code null}</td><td>/hotels</td><td>/hotels</td></tr>
|
* <tr><td>{@code null}</td><td>/hotels</td><td>/hotels</td></tr>
|
||||||
* <tr><td>/hotels</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
* <tr><td>/hotels</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
||||||
* <tr><td>/hotels</td><td>bookings</td><td>/hotels/bookings</td></tr>
|
* <tr><td>/hotels</td><td>bookings</td><td>/hotels/bookings</td></tr>
|
||||||
* <tr><td>/hotels/*</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
* <tr><td>/hotels/*</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
||||||
* <tr><td>/hotels/**</td><td>/bookings</td><td>/hotels/**/bookings</td></tr>
|
* <tr><td>/hotels/**</td><td>/bookings</td><td>/hotels/**/bookings</td></tr>
|
||||||
* <tr><td>/hotels</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
* <tr><td>/hotels</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
||||||
* <tr><td>/hotels/*</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
* <tr><td>/hotels/*</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
||||||
* <tr><td>/hotels/**</td><td>{hotel}</td><td>/hotels/**/{hotel}</td></tr>
|
* <tr><td>/hotels/**</td><td>{hotel}</td><td>/hotels/**/{hotel}</td></tr>
|
||||||
* <tr><td>/*.html</td><td>/hotels.html</td><td>/hotels.html</td></tr>
|
* <tr><td>/*.html</td><td>/hotels.html</td><td>/hotels.html</td></tr>
|
||||||
* <tr><td>/*.html</td><td>/hotels</td><td>/hotels.html</td></tr>
|
* <tr><td>/*.html</td><td>/hotels</td><td>/hotels.html</td></tr>
|
||||||
* <tr><td>/*.html</td><td>/*.txt</td><td>{@code IllegalArgumentException}</td></tr>
|
* <tr><td>/*.html</td><td>/*.txt</td><td>{@code IllegalArgumentException}</td></tr>
|
||||||
* </table>
|
* </table>
|
||||||
*
|
*
|
||||||
* @param pattern1 the first pattern
|
* @param pattern1 the first pattern
|
||||||
@ -677,6 +677,12 @@ public class AntPathMatcher {
|
|||||||
|
|
||||||
private final List<String> variableNames = new ArrayList<>();
|
private final List<String> variableNames = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code AntPathStringMatcher} that will match the supplied {@code pattern}
|
||||||
|
*
|
||||||
|
* @param pattern the pattern to match against
|
||||||
|
* @param caseSensitive 是否大小写不敏感
|
||||||
|
*/
|
||||||
public AntPathStringMatcher(final String pattern, final boolean caseSensitive) {
|
public AntPathStringMatcher(final String pattern, final boolean caseSensitive) {
|
||||||
this.rawPattern = pattern;
|
this.rawPattern = pattern;
|
||||||
this.caseSensitive = caseSensitive;
|
this.caseSensitive = caseSensitive;
|
||||||
@ -714,7 +720,7 @@ public class AntPathMatcher {
|
|||||||
this.exactMatch = false;
|
this.exactMatch = false;
|
||||||
patternBuilder.append(quote(pattern, end, pattern.length()));
|
patternBuilder.append(quote(pattern, end, pattern.length()));
|
||||||
this.pattern = (this.caseSensitive ? Pattern.compile(patternBuilder.toString()) :
|
this.pattern = (this.caseSensitive ? Pattern.compile(patternBuilder.toString()) :
|
||||||
Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE));
|
Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,15 +747,15 @@ public class AntPathMatcher {
|
|||||||
if (uriTemplateVariables != null) {
|
if (uriTemplateVariables != null) {
|
||||||
if (this.variableNames.size() != matcher.groupCount()) {
|
if (this.variableNames.size() != matcher.groupCount()) {
|
||||||
throw new IllegalArgumentException("The number of capturing groups in the pattern segment " +
|
throw new IllegalArgumentException("The number of capturing groups in the pattern segment " +
|
||||||
this.pattern + " does not match the number of URI template variables it defines, " +
|
this.pattern + " does not match the number of URI template variables it defines, " +
|
||||||
"which can occur if capturing groups are used in a URI template regex. " +
|
"which can occur if capturing groups are used in a URI template regex. " +
|
||||||
"Use non-capturing groups instead.");
|
"Use non-capturing groups instead.");
|
||||||
}
|
}
|
||||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||||
final String name = this.variableNames.get(i - 1);
|
final String name = this.variableNames.get(i - 1);
|
||||||
if (name.startsWith("*")) {
|
if (name.startsWith("*")) {
|
||||||
throw new IllegalArgumentException("Capturing patterns (" + name + ") are not " +
|
throw new IllegalArgumentException("Capturing patterns (" + name + ") are not " +
|
||||||
"supported by the AntPathMatcher. Use the PathPatternParser instead.");
|
"supported by the AntPathMatcher. Use the PathPatternParser instead.");
|
||||||
}
|
}
|
||||||
final String value = matcher.group(i);
|
final String value = matcher.group(i);
|
||||||
uriTemplateVariables.put(name, value);
|
uriTemplateVariables.put(name, value);
|
||||||
@ -769,18 +775,23 @@ public class AntPathMatcher {
|
|||||||
* {@link #getPatternComparator(String)}.
|
* {@link #getPatternComparator(String)}.
|
||||||
* <p>In order, the most "generic" pattern is determined by the following:
|
* <p>In order, the most "generic" pattern is determined by the following:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>if it's null or a capture all pattern (i.e. it is equal to "/**")</li>
|
* <li>if it's null or a capture all pattern (i.e. it is equal to "/**")</li>
|
||||||
* <li>if the other pattern is an actual match</li>
|
* <li>if the other pattern is an actual match</li>
|
||||||
* <li>if it's a catch-all pattern (i.e. it ends with "**"</li>
|
* <li>if it's a catch-all pattern (i.e. it ends with "**"</li>
|
||||||
* <li>if it's got more "*" than the other pattern</li>
|
* <li>if it's got more "*" than the other pattern</li>
|
||||||
* <li>if it's got more "{foo}" than the other pattern</li>
|
* <li>if it's got more "{foo}" than the other pattern</li>
|
||||||
* <li>if it's shorter than the other pattern</li>
|
* <li>if it's shorter than the other pattern</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
protected static class AntPatternComparator implements Comparator<String> {
|
protected static class AntPatternComparator implements Comparator<String> {
|
||||||
|
|
||||||
private final String path;
|
private final String path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param path 路径
|
||||||
|
*/
|
||||||
public AntPatternComparator(final String path) {
|
public AntPatternComparator(final String path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
@ -931,7 +942,7 @@ public class AntPathMatcher {
|
|||||||
public int getLength() {
|
public int getLength() {
|
||||||
if (this.length == null) {
|
if (this.length == null) {
|
||||||
this.length = (this.pattern != null ?
|
this.length = (this.pattern != null ?
|
||||||
VARIABLE_PATTERN.matcher(this.pattern).replaceAll("#").length() : 0);
|
VARIABLE_PATTERN.matcher(this.pattern).replaceAll("#").length() : 0);
|
||||||
}
|
}
|
||||||
return this.length;
|
return this.length;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ public abstract class AbstractFilter implements BloomFilter {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final BitSet bitSet;
|
private final BitSet bitSet;
|
||||||
|
/**
|
||||||
|
* 容量
|
||||||
|
*/
|
||||||
protected int size;
|
protected int size;
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@ import org.dromara.hutool.core.text.replacer.LookupReplacer;
|
|||||||
public class Html4Escape extends XmlEscape {
|
public class Html4Escape extends XmlEscape {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ISO8859_1 转义字符
|
||||||
|
*/
|
||||||
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
||||||
protected static final String[][] ISO8859_1_ESCAPE = { //
|
protected static final String[][] ISO8859_1_ESCAPE = { //
|
||||||
{ "\u00A0", " " }, // non-breaking space
|
{ "\u00A0", " " }, // non-breaking space
|
||||||
@ -124,6 +127,9 @@ public class Html4Escape extends XmlEscape {
|
|||||||
{ "\u00FF", "ÿ" }, // <EFBFBD> - lowercase y, umlaut
|
{ "\u00FF", "ÿ" }, // <EFBFBD> - lowercase y, umlaut
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML 4.01 extended entities.
|
||||||
|
*/
|
||||||
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
||||||
protected static final String[][] HTML40_EXTENDED_ESCAPE = {
|
protected static final String[][] HTML40_EXTENDED_ESCAPE = {
|
||||||
// <!-- Latin Extended-B -->
|
// <!-- Latin Extended-B -->
|
||||||
|
@ -18,14 +18,22 @@ import org.dromara.hutool.core.text.replacer.LookupReplacer;
|
|||||||
* HTML4的UNESCAPE
|
* HTML4的UNESCAPE
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class Html4Unescape extends XmlUnescape {
|
public class Html4Unescape extends XmlUnescape {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
protected static final String[][] ISO8859_1_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.ISO8859_1_ESCAPE);
|
/**
|
||||||
protected static final String[][] HTML40_EXTENDED_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.HTML40_EXTENDED_ESCAPE);
|
* ISO8859_1的UNESCAPE
|
||||||
|
*/
|
||||||
|
protected static final String[][] ISO8859_1_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.ISO8859_1_ESCAPE);
|
||||||
|
/**
|
||||||
|
* HTML40_EXTENDED的UNESCAPE
|
||||||
|
*/
|
||||||
|
protected static final String[][] HTML40_EXTENDED_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.HTML40_EXTENDED_ESCAPE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
public Html4Unescape() {
|
public Html4Unescape() {
|
||||||
super();
|
super();
|
||||||
addChain(new LookupReplacer(ISO8859_1_UNESCAPE));
|
addChain(new LookupReplacer(ISO8859_1_UNESCAPE));
|
||||||
|
@ -34,6 +34,9 @@ import org.dromara.hutool.core.text.replacer.ReplacerChain;
|
|||||||
public class XmlEscape extends ReplacerChain {
|
public class XmlEscape extends ReplacerChain {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML转义字符
|
||||||
|
*/
|
||||||
protected static final String[][] BASIC_ESCAPE = { //
|
protected static final String[][] BASIC_ESCAPE = { //
|
||||||
// {"'", "'"}, // " - single-quote
|
// {"'", "'"}, // " - single-quote
|
||||||
{"\"", """}, // " - double-quote
|
{"\"", """}, // " - double-quote
|
||||||
|
@ -24,8 +24,13 @@ import org.dromara.hutool.core.text.replacer.ReplacerChain;
|
|||||||
public class XmlUnescape extends ReplacerChain {
|
public class XmlUnescape extends ReplacerChain {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础反转义符
|
||||||
|
*/
|
||||||
protected static final String[][] BASIC_UNESCAPE = InternalEscapeUtil.invert(XmlEscape.BASIC_ESCAPE);
|
protected static final String[][] BASIC_UNESCAPE = InternalEscapeUtil.invert(XmlEscape.BASIC_ESCAPE);
|
||||||
// issue#1118
|
/**
|
||||||
|
* issue#1118,新增'反转义
|
||||||
|
*/
|
||||||
protected static final String[][] OTHER_UNESCAPE = new String[][]{new String[]{"'", "'"}};
|
protected static final String[][] OTHER_UNESCAPE = new String[][]{new String[]{"'", "'"}};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,8 +25,17 @@ import java.io.Serializable;
|
|||||||
public abstract class TextFinder implements Finder, Serializable {
|
public abstract class TextFinder implements Finder, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本
|
||||||
|
*/
|
||||||
protected CharSequence text;
|
protected CharSequence text;
|
||||||
|
/**
|
||||||
|
* 结束位置
|
||||||
|
*/
|
||||||
protected int endIndex = -1;
|
protected int endIndex = -1;
|
||||||
|
/**
|
||||||
|
* 是否反向查找
|
||||||
|
*/
|
||||||
protected boolean negative;
|
protected boolean negative;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,6 +151,15 @@ public abstract class StrTemplate {
|
|||||||
protected int fixedTextTotalLength;
|
protected int fixedTextTotalLength;
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param template 字符串模板
|
||||||
|
* @param escape 转义符
|
||||||
|
* @param defaultValue 默认值
|
||||||
|
* @param defaultValueHandler 默认值处理器
|
||||||
|
* @param features 策略值
|
||||||
|
*/
|
||||||
protected StrTemplate(final String template, final char escape, final String defaultValue,
|
protected StrTemplate(final String template, final char escape, final String defaultValue,
|
||||||
final UnaryOperator<String> defaultValueHandler, final int features) {
|
final UnaryOperator<String> defaultValueHandler, final int features) {
|
||||||
Assert.notNull(template, "String template cannot be null");
|
Assert.notNull(template, "String template cannot be null");
|
||||||
@ -718,6 +727,11 @@ public abstract class StrTemplate {
|
|||||||
*/
|
*/
|
||||||
protected int features;
|
protected int features;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param template 字符串模板
|
||||||
|
*/
|
||||||
protected AbstractBuilder(final String template) {
|
protected AbstractBuilder(final String template) {
|
||||||
this.template = Objects.requireNonNull(template);
|
this.template = Objects.requireNonNull(template);
|
||||||
// 策略值 初始为 全局默认策略
|
// 策略值 初始为 全局默认策略
|
||||||
|
@ -21,11 +21,15 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractPlaceholderSegment implements StrTemplateSegment {
|
public abstract class AbstractPlaceholderSegment implements StrTemplateSegment {
|
||||||
/**
|
/**
|
||||||
* 占位符变量
|
* 占位符变量,例如:{@literal "???"->"???", "{}"->"{}", "{name}"->"name"}
|
||||||
* <p>例如:{@literal "???"->"???", "{}"->"{}", "{name}"->"name"}</p>
|
|
||||||
*/
|
*/
|
||||||
private final String placeholder;
|
private final String placeholder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param placeholder 占位符变量,例如:{@literal "???"->"???", "{}"->"{}", "{name}"->"name"}
|
||||||
|
*/
|
||||||
protected AbstractPlaceholderSegment(final String placeholder) {
|
protected AbstractPlaceholderSegment(final String placeholder) {
|
||||||
this.placeholder = placeholder;
|
this.placeholder = placeholder;
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,23 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class IndexedPlaceholderSegment extends NamedPlaceholderSegment {
|
public class IndexedPlaceholderSegment extends NamedPlaceholderSegment {
|
||||||
/**
|
/**
|
||||||
* 下标值
|
* 下标值
|
||||||
*/
|
*/
|
||||||
private final int index;
|
private final int index;
|
||||||
|
|
||||||
public IndexedPlaceholderSegment(final String idxStr, final String wholePlaceholder) {
|
/**
|
||||||
super(idxStr, wholePlaceholder);
|
* 构造
|
||||||
this.index = Integer.parseInt(idxStr);
|
*
|
||||||
}
|
* @param idxStr 索引字符串变量
|
||||||
|
* @param wholePlaceholder 占位符完整文本
|
||||||
|
*/
|
||||||
|
public IndexedPlaceholderSegment(final String idxStr, final String wholePlaceholder) {
|
||||||
|
super(idxStr, wholePlaceholder);
|
||||||
|
this.index = Integer.parseInt(idxStr);
|
||||||
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,23 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class LiteralSegment implements StrTemplateSegment {
|
public class LiteralSegment implements StrTemplateSegment {
|
||||||
/**
|
/**
|
||||||
* 模板中固定的一段文本
|
* 模板中固定的一段文本
|
||||||
*/
|
*/
|
||||||
private final String text;
|
private final String text;
|
||||||
|
|
||||||
public LiteralSegment(final String text) {
|
/**
|
||||||
this.text = text;
|
* 构造
|
||||||
}
|
*
|
||||||
|
* @param text 文本
|
||||||
|
*/
|
||||||
|
public LiteralSegment(final String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText() {
|
public String getText() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,20 +20,25 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class NamedPlaceholderSegment extends AbstractPlaceholderSegment {
|
public class NamedPlaceholderSegment extends AbstractPlaceholderSegment {
|
||||||
/**
|
/**
|
||||||
* 占位符完整文本
|
* 占位符完整文本
|
||||||
* <p>例如:{@literal "{name}"->"{name}"}</p>
|
* <p>例如:{@literal "{name}"->"{name}"}</p>
|
||||||
*/
|
*/
|
||||||
private final String wholePlaceholder;
|
private final String wholePlaceholder;
|
||||||
|
|
||||||
public NamedPlaceholderSegment(final String name, final String wholePlaceholder) {
|
/**
|
||||||
super(name);
|
* 构造
|
||||||
this.wholePlaceholder = wholePlaceholder;
|
* @param name 占位符变量
|
||||||
}
|
* @param wholePlaceholder 占位符完整文本
|
||||||
|
*/
|
||||||
|
public NamedPlaceholderSegment(final String name, final String wholePlaceholder) {
|
||||||
|
super(name);
|
||||||
|
this.wholePlaceholder = wholePlaceholder;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText() {
|
public String getText() {
|
||||||
return wholePlaceholder;
|
return wholePlaceholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,17 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
|||||||
*/
|
*/
|
||||||
public class SinglePlaceholderSegment extends AbstractPlaceholderSegment {
|
public class SinglePlaceholderSegment extends AbstractPlaceholderSegment {
|
||||||
|
|
||||||
private SinglePlaceholderSegment(final String placeholder) {
|
private SinglePlaceholderSegment(final String placeholder) {
|
||||||
super(placeholder);
|
super(placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SinglePlaceholderSegment newInstance(final String placeholder) {
|
/**
|
||||||
return new SinglePlaceholderSegment(placeholder);
|
* 创建SinglePlaceholderSegment
|
||||||
}
|
*
|
||||||
|
* @param placeholder 占位符
|
||||||
|
* @return SinglePlaceholderSegment
|
||||||
|
*/
|
||||||
|
public static SinglePlaceholderSegment of(final String placeholder) {
|
||||||
|
return new SinglePlaceholderSegment(placeholder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,10 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public interface StrTemplateSegment {
|
public interface StrTemplateSegment {
|
||||||
/**
|
/**
|
||||||
* 获取文本值
|
* 获取文本值
|
||||||
*
|
*
|
||||||
* @return 文本值,对于固定文本Segment,返回文本值;对于单占位符Segment,返回占位符;对于有前后缀的占位符Segment,返回占位符完整文本,例如: "{name}"
|
* @return 文本值,对于固定文本Segment,返回文本值;对于单占位符Segment,返回占位符;对于有前后缀的占位符Segment,返回占位符完整文本,例如: "{name}"
|
||||||
*/
|
*/
|
||||||
String getText();
|
String getText();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -582,6 +582,10 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
|
|||||||
*/
|
*/
|
||||||
protected String suffix;
|
protected String suffix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
* @param template 模板
|
||||||
|
*/
|
||||||
protected Builder(final String template) {
|
protected Builder(final String template) {
|
||||||
super(template);
|
super(template);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public class SinglePlaceholderStrTemplate extends StrTemplate {
|
|||||||
// 上一个解析的segment是否是固定文本,如果是,则需要和当前新的文本部分合并
|
// 上一个解析的segment是否是固定文本,如果是,则需要和当前新的文本部分合并
|
||||||
boolean lastIsLiteralSegment = false;
|
boolean lastIsLiteralSegment = false;
|
||||||
// 复用的占位符变量
|
// 复用的占位符变量
|
||||||
final SinglePlaceholderSegment singlePlaceholderSegment = SinglePlaceholderSegment.newInstance(placeholder);
|
final SinglePlaceholderSegment singlePlaceholderSegment = SinglePlaceholderSegment.of(placeholder);
|
||||||
List<StrTemplateSegment> segments = null;
|
List<StrTemplateSegment> segments = null;
|
||||||
while (true) {
|
while (true) {
|
||||||
delimIndex = template.indexOf(placeholder, handledPosition);
|
delimIndex = template.indexOf(placeholder, handledPosition);
|
||||||
@ -200,6 +200,11 @@ public class SinglePlaceholderStrTemplate extends StrTemplate {
|
|||||||
*/
|
*/
|
||||||
protected String placeholder;
|
protected String placeholder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param template 字符串模板
|
||||||
|
*/
|
||||||
protected Builder(final String template) {
|
protected Builder(final String template) {
|
||||||
super(template);
|
super(template);
|
||||||
}
|
}
|
||||||
|
@ -12,39 +12,75 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.thread;
|
package org.dromara.hutool.core.thread;
|
||||||
|
|
||||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
import org.dromara.hutool.core.exception.HutoolException;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 工具类异常
|
* 线程异常
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
* @since 5.7.17
|
* @since 5.7.17
|
||||||
*/
|
*/
|
||||||
public class ThreadException extends RuntimeException {
|
public class ThreadException extends HutoolException {
|
||||||
private static final long serialVersionUID = 5253124428623713216L;
|
private static final long serialVersionUID = 5253124428623713216L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param e 异常
|
||||||
|
*/
|
||||||
public ThreadException(final Throwable e) {
|
public ThreadException(final Throwable e) {
|
||||||
super(ExceptionUtil.getMessage(e), e);
|
super(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
*/
|
||||||
public ThreadException(final String message) {
|
public ThreadException(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param messageTemplate 消息模板
|
||||||
|
* @param params 参数
|
||||||
|
*/
|
||||||
public ThreadException(final String messageTemplate, final Object... params) {
|
public ThreadException(final String messageTemplate, final Object... params) {
|
||||||
super(StrUtil.format(messageTemplate, params));
|
super(messageTemplate, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadException(final String message, final Throwable throwable) {
|
/**
|
||||||
super(message, throwable);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
*/
|
||||||
|
public ThreadException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadException(final String message, final Throwable throwable, final boolean enableSuppression, final boolean writableStackTrace) {
|
/**
|
||||||
super(message, throwable, enableSuppression, writableStackTrace);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param message 消息
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
* @param enableSuppression 是否启用抑制
|
||||||
|
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
||||||
|
*/
|
||||||
|
public ThreadException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadException(final Throwable throwable, final String messageTemplate, final Object... params) {
|
/**
|
||||||
super(StrUtil.format(messageTemplate, params), throwable);
|
* 构造
|
||||||
|
*
|
||||||
|
* @param cause 被包装的子异常
|
||||||
|
* @param messageTemplate 消息模板
|
||||||
|
* @param params 参数
|
||||||
|
*/
|
||||||
|
public ThreadException(final Throwable cause, final String messageTemplate, final Object... params) {
|
||||||
|
super(cause, messageTemplate, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,9 @@ import java.util.concurrent.locks.Lock;
|
|||||||
*/
|
*/
|
||||||
public class NoLock implements Lock{
|
public class NoLock implements Lock{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例
|
||||||
|
*/
|
||||||
public static NoLock INSTANCE = new NoLock();
|
public static NoLock INSTANCE = new NoLock();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
77
pom.xml
77
pom.xml
@ -57,12 +57,12 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Kotlin适配,用于在测试和编译中使用kotlin代码 -->
|
<!-- Kotlin适配,用于在测试中使用kotlin代码 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
<artifactId>kotlin-reflect</artifactId>
|
<artifactId>kotlin-reflect</artifactId>
|
||||||
<version>${kotlin-version}</version>
|
<version>${kotlin-version}</version>
|
||||||
<scope>provided</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- 全局单元测试 -->
|
<!-- 全局单元测试 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -100,6 +100,10 @@
|
|||||||
<name>VampireAchao</name>
|
<name>VampireAchao</name>
|
||||||
<email>VampireAchao@dromara.org</email>
|
<email>VampireAchao@dromara.org</email>
|
||||||
</developer>
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<name>CherryRum</name>
|
||||||
|
<email>yulin.1996@foxmail.com</email>
|
||||||
|
</developer>
|
||||||
<developer>
|
<developer>
|
||||||
<name>Emptypoint</name>
|
<name>Emptypoint</name>
|
||||||
<email>1215582715@qq.com</email>
|
<email>1215582715@qq.com</email>
|
||||||
@ -116,10 +120,6 @@
|
|||||||
<name>Dazer007</name>
|
<name>Dazer007</name>
|
||||||
<email>dazer007@163.com</email>
|
<email>dazer007@163.com</email>
|
||||||
</developer>
|
</developer>
|
||||||
<developer>
|
|
||||||
<name>CherryRum</name>
|
|
||||||
<email>yulin.1996@foxmail.com</email>
|
|
||||||
</developer>
|
|
||||||
<developer>
|
<developer>
|
||||||
<name>Aihuahua</name>
|
<name>Aihuahua</name>
|
||||||
<email>aihuahua522@qq.com</email>
|
<email>aihuahua522@qq.com</email>
|
||||||
@ -169,8 +169,10 @@
|
|||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.13.0</version>
|
<version>3.13.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<fork>true</fork>
|
||||||
<source>${compile.version}</source>
|
<source>${compile.version}</source>
|
||||||
<target>${compile.version}</target>
|
<target>${compile.version}</target>
|
||||||
|
<!-- 编译时启用警告位置 -->
|
||||||
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -214,46 +216,6 @@
|
|||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
<configuration>
|
|
||||||
<tags>
|
|
||||||
<tag>
|
|
||||||
<name>apiNote</name>
|
|
||||||
<placement>a</placement>
|
|
||||||
<head>API Note:</head>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>implSpec</name>
|
|
||||||
<placement>a</placement>
|
|
||||||
<head>Implementation Requirements:</head>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>implNote</name>
|
|
||||||
<placement>a</placement>
|
|
||||||
<head>Implementation Note:</head>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>param</name>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>return</name>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>throws</name>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>since</name>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>version</name>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>serialData</name>
|
|
||||||
</tag>
|
|
||||||
<tag>
|
|
||||||
<name>see</name>
|
|
||||||
</tag>
|
|
||||||
</tags>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
<!-- 统一更新pom版本 -->
|
<!-- 统一更新pom版本 -->
|
||||||
<plugin>
|
<plugin>
|
||||||
@ -277,6 +239,29 @@
|
|||||||
<check/>
|
<check/>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<!-- 用于生成模块化系统中的module-info.class,见:https://github.com/moditect/moditect -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.moditect</groupId>
|
||||||
|
<artifactId>moditect-maven-plugin</artifactId>
|
||||||
|
<version>1.2.2.Final</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add-module-infos</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-module-info</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<jvmVersion>9</jvmVersion>
|
||||||
|
<module>
|
||||||
|
<moduleInfo>
|
||||||
|
<name>${Automatic-Module-Name}</name>
|
||||||
|
</moduleInfo>
|
||||||
|
</module>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user