Merge branch 'dev' of http://zhouxy.xyz:3000/ZhouXY108/plusone-commons into dev
commit
a641144fbe
|
@ -6,6 +6,8 @@ import java.util.function.Function;
|
||||||
|
|
||||||
public class SafeConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
public class SafeConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 4352954948768449595L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new, empty map with the default initial table size (16).
|
* Creates a new, empty map with the default initial table size (16).
|
||||||
*/
|
*/
|
||||||
|
@ -75,6 +77,7 @@ public class SafeConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
||||||
super(initialCapacity, loadFactor, concurrencyLevel);
|
super(initialCapacity, loadFactor, concurrencyLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||||
V v = get(key);
|
V v = get(key);
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022-2023 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package xyz.zhouxy.plusone.commons.exception;
|
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
|
|
||||||
@Beta
|
|
||||||
public class DbException extends RuntimeException {
|
|
||||||
|
|
||||||
public DbException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -39,11 +39,11 @@ import xyz.zhouxy.plusone.commons.util.OptionalUtil;
|
||||||
public class DbRecord extends AbstractMapWrapper<String, Object, DbRecord> {
|
public class DbRecord extends AbstractMapWrapper<String, Object, DbRecord> {
|
||||||
|
|
||||||
public DbRecord() {
|
public DbRecord() {
|
||||||
super(new HashMap<>(), k -> Assert.isNotBlank(k, "Key can not be null."), null);
|
super(new HashMap<>(), k -> Assert.isNotBlank(k, "Key must has text."), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbRecord(Map<String, Object> map) {
|
public DbRecord(Map<String, Object> map) {
|
||||||
super(map, k -> Assert.isNotBlank(k, "Key can not be null."), null);
|
super(map, k -> Assert.isNotBlank(k, "Key must has text."), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<String> getValueAsString(String key) {
|
public Optional<String> getValueAsString(String key) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -35,11 +36,14 @@ import java.util.OptionalLong;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
import com.google.common.annotations.Beta;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import xyz.zhouxy.plusone.commons.util.Assert;
|
import xyz.zhouxy.plusone.commons.util.Assert;
|
||||||
import xyz.zhouxy.plusone.commons.util.MoreArrays;
|
import xyz.zhouxy.plusone.commons.util.MoreArrays;
|
||||||
|
import xyz.zhouxy.plusone.commons.util.MoreCollections;
|
||||||
import xyz.zhouxy.plusone.commons.util.OptionalUtil;
|
import xyz.zhouxy.plusone.commons.util.OptionalUtil;
|
||||||
|
|
||||||
@Beta
|
@Beta
|
||||||
|
@ -49,33 +53,6 @@ public class SimpleJdbcTemplate {
|
||||||
return new JdbcExecutor(conn);
|
return new JdbcExecutor(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object[] buildParams(final Object... params) {
|
|
||||||
return Arrays.stream(params)
|
|
||||||
.map(p -> {
|
|
||||||
if (p instanceof Optional) {
|
|
||||||
return OptionalUtil.orElseNull((Optional<?>) p);
|
|
||||||
}
|
|
||||||
if (p instanceof OptionalInt) {
|
|
||||||
OptionalInt _p = ((OptionalInt) p);
|
|
||||||
return _p.isPresent() ? _p.getAsInt() : null;
|
|
||||||
}
|
|
||||||
if (p instanceof OptionalLong) {
|
|
||||||
OptionalLong _p = ((OptionalLong) p);
|
|
||||||
return _p.isPresent() ? _p.getAsLong() : null;
|
|
||||||
}
|
|
||||||
if (p instanceof OptionalDouble) {
|
|
||||||
OptionalDouble _p = ((OptionalDouble) p);
|
|
||||||
return _p.isPresent() ? _p.getAsDouble() : null;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
})
|
|
||||||
.toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<Object[]> buildBatchParams(final Collection<T> c, Function<T, Object[]> function) {
|
|
||||||
return c.stream().map(function).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String paramsToString(Object[] params) {
|
public static String paramsToString(Object[] params) {
|
||||||
return Arrays.toString(params);
|
return Arrays.toString(params);
|
||||||
}
|
}
|
||||||
|
@ -252,4 +229,43 @@ public class SimpleJdbcTemplate {
|
||||||
void execute() throws SQLException, T;
|
void execute() throws SQLException, T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ParamBuilder {
|
||||||
|
|
||||||
|
public static Object[] buildParams(final Object... params) {
|
||||||
|
if (ArrayUtils.isEmpty(params)) {
|
||||||
|
return ArrayUtils.EMPTY_OBJECT_ARRAY;
|
||||||
|
}
|
||||||
|
return Arrays.stream(params)
|
||||||
|
.map(param -> {
|
||||||
|
if (param instanceof Optional) {
|
||||||
|
return OptionalUtil.orElseNull((Optional<?>) param);
|
||||||
|
}
|
||||||
|
if (param instanceof OptionalInt) {
|
||||||
|
return OptionalUtil.toInteger(((OptionalInt) param));
|
||||||
|
}
|
||||||
|
if (param instanceof OptionalLong) {
|
||||||
|
return OptionalUtil.toLong(((OptionalLong) param));
|
||||||
|
}
|
||||||
|
if (param instanceof OptionalDouble) {
|
||||||
|
return OptionalUtil.toDouble(((OptionalDouble) param));
|
||||||
|
}
|
||||||
|
return param;
|
||||||
|
})
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<Object[]> buildBatchParams(final Collection<T> c, final Function<T, Object[]> function) {
|
||||||
|
Assert.notNull(c, "The collection can not be null.");
|
||||||
|
Assert.notNull(function, "The function can not be null.");
|
||||||
|
if (MoreCollections.isEmpty(c)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return c.stream().map(function).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParamBuilder() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,10 +70,25 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
|
||||||
* @throws IllegalArgumentException key 不存在时抛出。
|
* @throws IllegalArgumentException key 不存在时抛出。
|
||||||
*/
|
*/
|
||||||
public Optional<V> get(K key) {
|
public Optional<V> get(K key) {
|
||||||
if (this.map.containsKey(key)) {
|
if (!this.map.containsKey(key)) {
|
||||||
return Optional.ofNullable(this.map.get(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")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -149,7 +164,7 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
|
||||||
return this.map.toString();
|
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 final Map<K, V> map;
|
||||||
protected Consumer<K> keyChecker;
|
protected Consumer<K> keyChecker;
|
||||||
protected Consumer<V> valueChecker;
|
protected Consumer<V> valueChecker;
|
||||||
|
@ -158,17 +173,17 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
|
||||||
this.map = map;
|
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;
|
this.keyChecker = keyChecker;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder<K, V> valueChecker(@Nullable Consumer<V> valueChecker) {
|
public Builder<K, V, T> valueChecker(@Nullable Consumer<V> valueChecker) {
|
||||||
this.valueChecker = valueChecker;
|
this.valueChecker = valueChecker;
|
||||||
return this;
|
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) {
|
if (this.keyChecker != null) {
|
||||||
this.keyChecker.accept(key);
|
this.keyChecker.accept(key);
|
||||||
}
|
}
|
||||||
|
@ -179,15 +194,15 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
|
||||||
return this;
|
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()) {
|
for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
|
||||||
put(entry.getKey(), entry.getValue());
|
put(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract MapWrapper<K, V> build();
|
public abstract T build();
|
||||||
|
|
||||||
public abstract MapWrapper<K, V> buildUnmodifiableMap();
|
public abstract T buildUnmodifiableMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,54 +78,45 @@ public class Assert {
|
||||||
}
|
}
|
||||||
|
|
||||||
// between - int
|
// 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 {
|
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) {
|
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) {
|
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
|
// 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 {
|
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) {
|
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) {
|
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
|
// 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 {
|
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) {
|
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) {
|
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
|
// notNull
|
||||||
|
|
|
@ -61,7 +61,7 @@ public final class MapWrapper<K, V> extends AbstractMapWrapper<K, V, MapWrapper<
|
||||||
return new Builder<>(new TreeMap<>(comparator));
|
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) {
|
private Builder(Map<K, V> map) {
|
||||||
super(map);
|
super(map);
|
||||||
|
|
|
@ -21,12 +21,14 @@ package xyz.zhouxy.plusone.commons.util;
|
||||||
*
|
*
|
||||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||||
*/
|
*/
|
||||||
public class NumberUtil {
|
public class Numbers {
|
||||||
|
|
||||||
private NumberUtil() {
|
private Numbers() {
|
||||||
throw new IllegalStateException("Utility class");
|
throw new IllegalStateException("Utility class");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sum
|
||||||
|
|
||||||
public static int sum(final short... numbers) {
|
public static int sum(final short... numbers) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (short number : numbers) {
|
for (short number : numbers) {
|
||||||
|
@ -66,4 +68,26 @@ public class NumberUtil {
|
||||||
}
|
}
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -134,6 +134,21 @@ public class OptionalUtil {
|
||||||
return optionalObj.orElse(null);
|
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() {
|
private OptionalUtil() {
|
||||||
throw new IllegalStateException("Utility class");
|
throw new IllegalStateException("Utility class");
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,42 +16,131 @@
|
||||||
|
|
||||||
package xyz.zhouxy.plusone.commons.util;
|
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 javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import xyz.zhouxy.plusone.commons.collection.SafeConcurrentHashMap;
|
import xyz.zhouxy.plusone.commons.collection.SafeConcurrentHashMap;
|
||||||
|
|
||||||
import java.util.Map;
|
/**
|
||||||
import java.util.Objects;
|
* 封装一些常用的正则操作,并可以缓存 {@link Pattern} 实例以复用(最多缓存 256 个)。
|
||||||
import java.util.regex.Pattern;
|
*
|
||||||
|
* @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<>();
|
/**
|
||||||
|
* 获取 {@link Pattern} 实例。
|
||||||
public static Pattern getPattern(final String regex) {
|
*
|
||||||
Objects.requireNonNull(regex);
|
* @param pattern 正则表达式
|
||||||
return PATTERN_CACHE.computeIfAbsent(regex, Pattern::compile);
|
* @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();
|
return input != null && pattern.matcher(input).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean matchesOr(@Nullable CharSequence input, String... regexes) {
|
/**
|
||||||
for (String regex : regexes) {
|
* 判断 {@code input} 是否匹配 {@code patterns} 中的一个。
|
||||||
if (matches(input, regex)) {
|
*
|
||||||
return true;
|
* @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) {
|
for (Pattern pattern : patterns) {
|
||||||
if (matches(input, pattern)) {
|
if (matches(input, pattern)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -60,16 +149,18 @@ public class RegexUtil {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean matchesAnd(@Nullable CharSequence input, String... regexes) {
|
/**
|
||||||
for (String regex : regexes) {
|
* 判断 {@code input} 是否匹配全部正则。
|
||||||
if (!matches(input, regex)) {
|
*
|
||||||
return false;
|
* @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) {
|
for (Pattern pattern : patterns) {
|
||||||
if (!matches(input, pattern)) {
|
if (!matches(input, pattern)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -78,7 +169,122 @@ public class RegexUtil {
|
||||||
return true;
|
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() {
|
private RegexUtil() {
|
||||||
|
// 不允许实例化
|
||||||
throw new IllegalStateException("Utility class");
|
throw new IllegalStateException("Utility class");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package xyz.zhouxy.plusone.commons.function;
|
package xyz.zhouxy.plusone.commons.function;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import xyz.zhouxy.plusone.commons.util.Assert;
|
|
||||||
|
|
||||||
class FunctionTests {
|
class FunctionTests {
|
||||||
|
|
||||||
|
@ -14,6 +15,6 @@ class FunctionTests {
|
||||||
String str = "";
|
String str = "";
|
||||||
Predicate<String> predicate = Predicates.<String>of(Objects::nonNull)
|
Predicate<String> predicate = Predicates.<String>of(Objects::nonNull)
|
||||||
.and(StringUtils::isNotBlank);
|
.and(StringUtils::isNotBlank);
|
||||||
Assert.isFalse(predicate.test(str), "校验应是不通过");
|
assertFalse(predicate.test(str), "校验应是不通过");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package xyz.zhouxy.plusone.commons.util;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static xyz.zhouxy.plusone.commons.jdbc.JdbcSql.IN;
|
import static xyz.zhouxy.plusone.commons.jdbc.JdbcSql.IN;
|
||||||
|
import static xyz.zhouxy.plusone.commons.jdbc.SimpleJdbcTemplate.ParamBuilder.*;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
@ -49,7 +50,7 @@ class SimpleJdbcTemplateTests {
|
||||||
@Test
|
@Test
|
||||||
void testQuery() throws SQLException {
|
void testQuery() throws SQLException {
|
||||||
try (Connection conn = this.dataSource.getConnection()) {
|
try (Connection conn = this.dataSource.getConnection()) {
|
||||||
Object[] params = SimpleJdbcTemplate.buildParams("501533", "501554", "544599");
|
Object[] params = buildParams("501533", "501554", "544599");
|
||||||
String sql = SQL.newJdbcSql()
|
String sql = SQL.newJdbcSql()
|
||||||
.SELECT("*")
|
.SELECT("*")
|
||||||
.FROM("test_table")
|
.FROM("test_table")
|
||||||
|
|
Loading…
Reference in New Issue