This commit is contained in:
2023-06-28 01:13:06 +08:00
12 changed files with 366 additions and 129 deletions

View File

@@ -70,10 +70,25 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
* @throws IllegalArgumentException key 不存在时抛出。
*/
public Optional<V> get(K key) {
if (this.map.containsKey(key)) {
return Optional.ofNullable(this.map.get(key));
if (!this.map.containsKey(key)) {
throw new IllegalArgumentException("Key does not exist");
}
throw new IllegalArgumentException("Key does not exist");
return Optional.ofNullable(this.map.get(key));
}
/**
* 获取 {@code map} 中的值。如果 {@code key} 不存在,则抛出异常。
*
* @param key 键
* @return 值
* @throws IllegalArgumentException key 不存在时抛出。
*/
@Nullable
public V getOrNull(K key) {
if (!this.map.containsKey(key)) {
throw new IllegalArgumentException("Key does not exist");
}
return this.map.get(key);
}
@SuppressWarnings("unchecked")
@@ -149,7 +164,7 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
return this.map.toString();
}
protected abstract static class Builder<K, V> {
protected abstract static class Builder<K, V, T extends AbstractMapWrapper<K, V, T>> {
protected final Map<K, V> map;
protected Consumer<K> keyChecker;
protected Consumer<V> valueChecker;
@@ -158,17 +173,17 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
this.map = map;
}
public Builder<K, V> keyChecker(@Nullable Consumer<K> keyChecker) {
public Builder<K, V, T> keyChecker(@Nullable Consumer<K> keyChecker) {
this.keyChecker = keyChecker;
return this;
}
public Builder<K, V> valueChecker(@Nullable Consumer<V> valueChecker) {
public Builder<K, V, T> valueChecker(@Nullable Consumer<V> valueChecker) {
this.valueChecker = valueChecker;
return this;
}
public Builder<K, V> put(K key, V value) {
public Builder<K, V, T> put(K key, V value) {
if (this.keyChecker != null) {
this.keyChecker.accept(key);
}
@@ -179,15 +194,15 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
return this;
}
public Builder<K, V> putAll(Map<? extends K, ? extends V> m) {
public Builder<K, V, T> putAll(Map<? extends K, ? extends V> m) {
for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
return this;
}
public abstract MapWrapper<K, V> build();
public abstract T build();
public abstract MapWrapper<K, V> buildUnmodifiableMap();
public abstract T buildUnmodifiableMap();
}
}

View File

@@ -78,54 +78,45 @@ public class Assert {
}
// between - int
private static boolean between(int value, int min, int max) {
return value >= min && value < max;
}
public static <E extends Throwable> void between(int value, int min, int max, Supplier<E> e) throws E {
Assert.isTrue(between(value, min, max), e);
Assert.isTrue(Numbers.between(value, min, max), e);
}
public static void between(int value, int min, int max, String errorMessage) {
Assert.isTrue(between(value, min, max), errorMessage);
Assert.isTrue(Numbers.between(value, min, max), errorMessage);
}
public static void between(int value, int min, int max, String errorMessageTemplate, Object... args) {
Assert.isTrue(between(value, min, max), errorMessageTemplate, args);
Assert.isTrue(Numbers.between(value, min, max), errorMessageTemplate, args);
}
// between - long
private static boolean between(long value, long min, long max) {
return value >= min && value < max;
}
public static <E extends Throwable> void between(long value, long min, long max, Supplier<E> e) throws E {
Assert.isTrue(between(value, min, max), e);
Assert.isTrue(Numbers.between(value, min, max), e);
}
public static void between(long value, long min, long max, String errorMessage) {
Assert.isTrue(between(value, min, max), errorMessage);
Assert.isTrue(Numbers.between(value, min, max), errorMessage);
}
public static void between(long value, long min, long max, String errorMessageTemplate, Object... args) {
Assert.isTrue(between(value, min, max), errorMessageTemplate, args);
Assert.isTrue(Numbers.between(value, min, max), errorMessageTemplate, args);
}
// between - double
private static boolean between(double value, double min, double max) {
return value >= min && value < max;
}
public static <E extends Throwable> void between(double value, double min, double max, Supplier<E> e) throws E {
Assert.isTrue(between(value, min, max), e);
Assert.isTrue(Numbers.between(value, min, max), e);
}
public static void between(double value, double min, double max, String errorMessage) {
Assert.isTrue(between(value, min, max), errorMessage);
Assert.isTrue(Numbers.between(value, min, max), errorMessage);
}
public static void between(double value, double min, double max, String errorMessageTemplate, Object... args) {
Assert.isTrue(between(value, min, max), errorMessageTemplate, args);
Assert.isTrue(Numbers.between(value, min, max), errorMessageTemplate, args);
}
// notNull

View File

@@ -61,7 +61,7 @@ public final class MapWrapper<K, V> extends AbstractMapWrapper<K, V, MapWrapper<
return new Builder<>(new TreeMap<>(comparator));
}
public static final class Builder<K, V> extends AbstractMapWrapper.Builder<K, V> {
public static final class Builder<K, V> extends AbstractMapWrapper.Builder<K, V, MapWrapper<K, V>> {
private Builder(Map<K, V> map) {
super(map);

View File

@@ -21,12 +21,14 @@ package xyz.zhouxy.plusone.commons.util;
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public class NumberUtil {
public class Numbers {
private NumberUtil() {
private Numbers() {
throw new IllegalStateException("Utility class");
}
// sum
public static int sum(final short... numbers) {
int result = 0;
for (short number : numbers) {
@@ -66,4 +68,26 @@ public class NumberUtil {
}
return result;
}
// between
public static boolean between(short value, short min, short max) {
return value >= min && value < max;
}
public static boolean between(int value, int min, int max) {
return value >= min && value < max;
}
public static boolean between(long value, long min, long max) {
return value >= min && value < max;
}
public static boolean between(float value, float min, float max) {
return value >= min && value < max;
}
public static boolean between(double value, double min, double max) {
return value >= min && value < max;
}
}

View File

@@ -134,6 +134,21 @@ public class OptionalUtil {
return optionalObj.orElse(null);
}
@Beta
public static Integer toInteger(OptionalInt optionalObj) {
return optionalObj.isPresent() ? optionalObj.getAsInt() : null;
}
@Beta
public static Long toLong(OptionalLong optionalObj) {
return optionalObj.isPresent() ? optionalObj.getAsLong() : null;
}
@Beta
public static Double toDouble(OptionalDouble optionalObj) {
return optionalObj.isPresent() ? optionalObj.getAsDouble() : null;
}
private OptionalUtil() {
throw new IllegalStateException("Utility class");
}

View File

@@ -16,42 +16,131 @@
package xyz.zhouxy.plusone.commons.util;
import java.util.Arrays;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import com.google.common.base.Preconditions;
import xyz.zhouxy.plusone.commons.collection.SafeConcurrentHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
/**
* 封装一些常用的正则操作,并可以缓存 {@link Pattern} 实例以复用(最多缓存 256 个)。
*
* @author ZhouXY
*
*/
public final class RegexUtil {
public class RegexUtil {
private static final int DEFAULT_CACHE_INITIAL_CAPACITY = 64;
private static final int MAX_CACHE_SIZE = 256;
private static final Map<String, Pattern> PATTERN_CACHE = new SafeConcurrentHashMap<>(
DEFAULT_CACHE_INITIAL_CAPACITY);
private static final Map<String, Pattern> PATTERN_CACHE = new SafeConcurrentHashMap<>();
public static Pattern getPattern(final String regex) {
Objects.requireNonNull(regex);
return PATTERN_CACHE.computeIfAbsent(regex, Pattern::compile);
/**
* 获取 {@link Pattern} 实例。
*
* @param pattern 正则表达式
* @param cachePattern 是否缓存 {@link Pattern} 实例
* @return {@link Pattern} 实例
*/
public static Pattern getPattern(final String pattern, final boolean cachePattern) {
Preconditions.checkNotNull(pattern, "The pattern can not be null.");
Pattern result = PATTERN_CACHE.get(pattern);
if (result == null) {
result = Pattern.compile(pattern);
if (cachePattern && PATTERN_CACHE.size() < MAX_CACHE_SIZE) {
PATTERN_CACHE.putIfAbsent(pattern, result);
result = PATTERN_CACHE.get(pattern);
}
}
return result;
}
public static boolean matches(@Nullable CharSequence input, String regex) {
return matches(input, getPattern(regex));
/**
* 获取 {@link Pattern} 实例,不缓存。
*
* @param pattern 正则表达式
* @return {@link Pattern} 实例
*/
public static Pattern getPattern(final String pattern) {
Preconditions.checkNotNull(pattern, "The pattern can not be null.");
Pattern result = PATTERN_CACHE.get(pattern);
if (result == null) {
result = Pattern.compile(pattern);
}
return result;
}
public static boolean matches(@Nullable CharSequence input, Pattern pattern) {
Assert.notNull(pattern, "Pattern must not be null.");
/**
* 将各个正则表达式转为 {@link Pattern} 实例。
*
* @param patterns 正则表达式
* @param cachePattern 是否缓存 {@link Pattern} 实例
* @return {@link Pattern} 实例数组
*/
public static Pattern[] getPatterns(final String[] patterns, final boolean cachePattern) {
Preconditions.checkNotNull(patterns, "The patterns can not be null.");
return Arrays.stream(patterns)
.map(pattern -> getPattern(pattern, cachePattern))
.toArray(Pattern[]::new);
}
/**
* 将各个正则表达式转为 {@link Pattern} 实例,不缓存。
*
* @param patterns 正则表达式
* @return {@link Pattern} 实例数组
*/
public static Pattern[] getPatterns(final String[] patterns) {
Preconditions.checkNotNull(patterns, "The patterns can not be null.");
return Arrays.stream(patterns)
.map(RegexUtil::getPattern)
.toArray(Pattern[]::new);
}
/**
* 手动缓存 Pattern 实例。
*
* @param pattern 要缓存的 {@link Pattern} 实例
* @return 缓存的 Pattern 实例。如果缓存已满,则返回 {@code null}。
*/
public static Pattern cachePattern(final Pattern pattern) {
if (PATTERN_CACHE.size() >= MAX_CACHE_SIZE) {
return null;
}
final String patternStr = pattern.pattern();
PATTERN_CACHE.putIfAbsent(patternStr, pattern);
return PATTERN_CACHE.get(patternStr);
}
/**
* 判断 {@code input} 是否匹配 {@code pattern}。
*
* @param input 输入
* @param pattern 正则
* @return 判断结果
*/
public static boolean matches(@Nullable final CharSequence input, final Pattern pattern) {
Preconditions.checkNotNull(pattern, "The pattern can not be null.");
return input != null && pattern.matcher(input).matches();
}
public static boolean matchesOr(@Nullable CharSequence input, String... regexes) {
for (String regex : regexes) {
if (matches(input, regex)) {
return true;
}
/**
* 判断 {@code input} 是否匹配 {@code patterns} 中的一个。
*
* @param input 输入
* @param patterns 正则
* @return 判断结果
*/
public static boolean matchOne(@Nullable final CharSequence input, final Pattern[] patterns) {
Preconditions.checkNotNull(patterns, "The patterns can not be null.");
if (input == null) {
return false;
}
return false;
}
public static boolean matchesOr(@Nullable CharSequence input, Pattern... patterns) {
for (Pattern pattern : patterns) {
if (matches(input, pattern)) {
return true;
@@ -60,16 +149,18 @@ public class RegexUtil {
return false;
}
public static boolean matchesAnd(@Nullable CharSequence input, String... regexes) {
for (String regex : regexes) {
if (!matches(input, regex)) {
return false;
}
/**
* 判断 {@code input} 是否匹配全部正则。
*
* @param input 输入
* @param patterns 正则
* @return 判断结果
*/
public static boolean matchAll(@Nullable final CharSequence input, final Pattern[] patterns) {
Preconditions.checkNotNull(patterns, "The patterns can not be null.");
if (input == null) {
return false;
}
return true;
}
public static boolean matchesAnd(@Nullable CharSequence input, Pattern... patterns) {
for (Pattern pattern : patterns) {
if (!matches(input, pattern)) {
return false;
@@ -78,7 +169,122 @@ public class RegexUtil {
return true;
}
/**
* 判断 {@code input} 是否匹配 {@code pattern}。
*
* @param input 输入
* @param pattern 正则表达式
* @param cachePattern 是否缓存 {@link Pattern} 实例
* @return 判断结果
*/
public static boolean matches(@Nullable final CharSequence input, final String pattern,
final boolean cachePattern) {
return matches(input, getPattern(pattern, cachePattern));
}
/**
* 判断 {@code input} 是否匹配 {@code pattern}。不缓存 {@link Pattern} 实例。
*
* @param input 输入
* @param pattern 正则表达式
* @return 判断结果
*/
public static boolean matches(@Nullable final CharSequence input, final String pattern) {
return matches(input, getPattern(pattern));
}
/**
* 判断 {@code input} 是否匹配 {@code patterns} 中的一个。
*
* @param input 输入
* @param patterns 正则表达式
* @param cachePattern 是否缓存 {@link Pattern} 实例
* @return 判断结果
*/
public static boolean matchOne(@Nullable final CharSequence input, final String[] patterns,
final boolean cachePattern) {
final Pattern[] patternSet = getPatterns(patterns, cachePattern);
return matchOne(input, patternSet);
}
/**
* 判断 {@code input} 是否匹配 {@code patterns} 中的一个。不缓存 {@link Pattern} 实例。
*
* @param input 输入
* @param patterns 正则表达式
* @return 判断结果
*/
public static boolean matchOne(@Nullable final CharSequence input, final String[] patterns) {
final Pattern[] patternSet = getPatterns(patterns);
return matchOne(input, patternSet);
}
/**
* 判断 {@code input} 是否匹配全部正则。
*
* @param input 输入
* @param patterns 正则表达式
* @param cachePattern 是否缓存 {@link Pattern} 实例
* @return 判断结果
*/
public static boolean matchAll(@Nullable final CharSequence input, final String[] patterns,
final boolean cachePattern) {
final Pattern[] patternSet = getPatterns(patterns, cachePattern);
return matchAll(input, patternSet);
}
/**
* 判断 {@code input} 是否匹配全部正则。不缓存 {@link Pattern} 实例。
*
* @param input 输入
* @param patterns 正则表达式
* @return 判断结果
*/
public static boolean matchAll(@Nullable final CharSequence input, final String[] patterns) {
final Pattern[] patternSet = getPatterns(patterns);
return matchAll(input, patternSet);
}
/**
* 生成匹配器。
*
* @param input 输入
* @param pattern 正则
* @return 结果
*/
public static Matcher getMatcher(final CharSequence input, final Pattern pattern) {
Preconditions.checkNotNull(input, "The input can not be null");
Preconditions.checkNotNull(pattern, "The pattern can not be null");
return pattern.matcher(input);
}
/**
* 生成匹配器。
*
* @param input 输入
* @param pattern 正则表达式
* @param cachePattern 是否缓存 {@link Pattern} 实例
* @return 结果
*/
public static Matcher getMatcher(final CharSequence input, final String pattern, boolean cachePattern) {
Preconditions.checkNotNull(input, "The input can not be null");
return getPattern(pattern, cachePattern).matcher(input);
}
/**
* 生成匹配器。不缓存 {@link Pattern} 实例。
*
* @param input 输入
* @param pattern 正则表达式
* @return 结果
*/
public static Matcher getMatcher(final CharSequence input, final String pattern) {
Preconditions.checkNotNull(input, "The input can not be null");
return getPattern(pattern).matcher(input);
}
private RegexUtil() {
// 不允许实例化
throw new IllegalStateException("Utility class");
}
}