This commit is contained in:
Looly 2024-08-20 18:12:26 +08:00
parent 65fd58e690
commit 1fa28d6fde
13 changed files with 206 additions and 178 deletions

View File

@ -18,18 +18,13 @@ package org.dromara.hutool.core.collection;
import org.dromara.hutool.core.collection.set.SetUtil;
import org.dromara.hutool.core.func.SerFunction;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.stream.CollectorUtil;
import org.dromara.hutool.core.stream.StreamUtil;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collector;
@ -53,7 +48,7 @@ public class CollStreamUtil {
* @param <K> map中的key类型
* @return 转化后的map
*/
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final Function<V, K> key) {
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final SerFunction<V, K> key) {
return toIdentityMap(collection, key, false);
}
@ -69,7 +64,7 @@ public class CollStreamUtil {
* @param <K> map中的key类型
* @return 转化后的map
*/
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final Function<V, K> key, final boolean isParallel) {
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final SerFunction<V, K> key, final boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return MapUtil.zero();
}
@ -230,8 +225,8 @@ public class CollStreamUtil {
* @param <V> List中的value类型
* @return 分组后的map
*/
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final Function<E, K> key,
final Function<E, V> value) {
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final SerFunction<E, K> key,
final SerFunction<E, V> value) {
return groupKeyValue(collection, key, value, false);
}
@ -248,8 +243,8 @@ public class CollStreamUtil {
* @param <V> List中的value类型
* @return 分组后的map
*/
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final Function<E, K> key,
final Function<E, V> value, final boolean isParallel) {
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final SerFunction<E, K> key,
final SerFunction<E, V> value, final boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return MapUtil.zero();
}

View File

@ -15,6 +15,9 @@
*/
package org.dromara.hutool.core.lang;
import org.dromara.hutool.core.func.SerConsumer;
import org.dromara.hutool.core.func.SerFunction;
import org.dromara.hutool.core.func.SerPredicate;
import org.dromara.hutool.core.func.SerSupplier;
import org.dromara.hutool.core.stream.EasyStream;
import org.dromara.hutool.core.text.StrUtil;
@ -27,7 +30,6 @@ import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
@ -128,7 +130,7 @@ public class Opt<T> {
* @since 6.0.0
*/
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public static <T> Opt<T> of(final Optional<T> optional) {
public static <T> Opt<T> of(final Optional<? extends T> optional) {
return ofNullable(optional.orElse(null));
}
@ -166,7 +168,6 @@ public class Opt<T> {
* 判断包裹里元素的值是否不存在不存在为 {@code true}否则为{@code false}
*
* @return 包裹里元素的值不存在 则为 {@code true}否则为{@code false}
* @since 11 这是jdk11{@link java.util.Optional}中的新函数
*/
public boolean isEmpty() {
return value == null;
@ -261,74 +262,59 @@ public class Opt<T> {
* @return this
* @throws NullPointerException 如果包裹里的值存在但你传入的操作为{@code null}时抛出
*/
public Opt<T> ifPresent(final Consumer<? super T> action) {
public Opt<T> ifPresent(final SerConsumer<? super T> action) {
if (isPresent()) {
action.accept(value);
try {
action.accepting(value);
} catch (final Throwable e) {
this.throwable = e;
}
}
return this;
}
/**
* 判断包裹里的值存在并且与给定的条件是否满足 ({@link Predicate#test}执行结果是否为true)
* 如果满足条件则返回本身
* 不满足条件或者元素本身为空时返回一个返回一个空的{@code Opt}
* 如果满足条件则返回本身<br>
* 不满足条件或者元素本身为空时返回一个返回一个空的{@code Opt}<br>
* predicate测试报错则返回一个空的{@code Opt}并附带错误信息
*
* @param predicate 给定的条件
* @return 如果满足条件则返回本身, 不满足条件或者元素本身为空时返回一个空的{@code Opt}
* @throws NullPointerException 如果给定的条件为 {@code null}抛出{@code NPE}
*/
public Opt<T> filter(final Predicate<? super T> predicate) {
public Opt<T> filter(final SerPredicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (isEmpty() || isFail()) {
return this;
} else {
return predicate.test(value) ? this : empty();
}
try {
return predicate.testing(value) ? this : empty();
} catch (final Throwable e) {
return createError(e);
}
}
/**
* 如果包裹里的值存在就执行传入的操作({@link Function#apply})并返回一个包裹了该操作返回值的{@code Opt}
* 如果包裹里的值存在就执行传入的操作({@link SerFunction#applying(Object)})并返回一个包裹了该操作返回值的{@code Opt}
* 如果不存在返回一个空的{@code Opt}
*
* @param mapper 值存在时执行的操作
* @param <U> 操作返回值的类型
* @return 如果包裹里的值存在就执行传入的操作({@link Function#apply})并返回一个包裹了该操作返回值的{@code Opt}
* @return 如果包裹里的值存在就执行传入的操作({@link SerFunction#applying(Object)})并返回一个包裹了该操作返回值的{@code Opt}
* 如果不存在返回一个空的{@code Opt}
* @throws NullPointerException 如果给定的操作为 {@code null}抛出 {@code NPE}
*/
@SuppressWarnings("unchecked")
public <U> Opt<U> map(final Function<? super T, ? extends U> mapper) {
public <U> Opt<U> map(final SerFunction<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (isFail()) {
return (Opt<U>) this;
} else if (isEmpty()) {
return empty();
} else {
return Opt.ofNullable(mapper.apply(value));
}
}
/**
* 如果包裹里的值存在就执行传入的操作({@link Function#apply})并返回该操作返回值
* 如果不存在返回一个空的{@code Opt}
* {@link Opt#map}的区别为 传入的操作返回值必须为 Opt
*
* @param mapper 值存在时执行的操作
* @param <U> 操作返回值的类型
* @return 如果包裹里的值存在就执行传入的操作({@link Function#apply})并返回该操作返回值
* 如果不存在返回一个空的{@code Opt}
* @throws NullPointerException 如果给定的操作为 {@code null}或者给定的操作执行结果为 {@code null}抛出 {@code NPE}
*/
@SuppressWarnings("unchecked")
public <U> Opt<U> flatMap(final Function<? super T, ? extends Opt<? extends U>> mapper) {
Objects.requireNonNull(mapper);
if (isFail()) {
return (Opt<U>) this;
} else if (isEmpty()) {
return empty();
} else {
@SuppressWarnings("unchecked") final Opt<U> r = (Opt<U>) mapper.apply(value);
return Objects.requireNonNull(r);
return Opt.ofTry(() -> mapper.applying(value));
}
}
@ -346,39 +332,28 @@ public class Opt<T> {
* @since 5.7.16
*/
@SuppressWarnings("unchecked")
public <U> Opt<U> flattedMap(final Function<? super T, ? extends Optional<? extends U>> mapper) {
public <U> Opt<U> flattedMap(final SerFunction<? super T, ? extends Optional<? extends U>> mapper) {
Objects.requireNonNull(mapper);
if (isFail()) {
return (Opt<U>) this;
} else if (isEmpty()) {
return empty();
} else {
return ofNullable(mapper.apply(value).orElse(null));
final Optional<? extends U> optional;
try {
optional = mapper.applying(value);
} catch (final Throwable e) {
return createError(e);
}
return of(optional);
}
}
/**
* 如果包裹里元素的值存在就执行对应的操作并返回本身
* 如果不存在返回一个空的{@code Opt}
*
* <p>属于 {@link #ifPresent}的链式拓展
*
* @param action 值存在时执行的操作
* @return this
* @throws NullPointerException 如果值存在并且传入的操作为 {@code null}
* @author VampireAchao
*/
public Opt<T> peek(final Consumer<T> action) throws NullPointerException {
return ifPresent(action);
}
/**
* 如果包裹里元素的值存在就执行对应的操作集并返回本身
* 如果不存在返回一个空的{@code Opt}
*
* <p>属于 {@link #ifPresent}的链式拓展
* <p>属于 {@link #peek(Consumer)}的动态拓展
* <p>属于 {@link #ifPresent(SerConsumer)}的动态拓展
*
* @param actions 值存在时执行的操作动态参数可传入数组当数组为一个空数组时并不会抛出 {@code NPE}
* @return this
@ -386,9 +361,8 @@ public class Opt<T> {
* @author VampireAchao
*/
@SafeVarargs
public final Opt<T> peeks(final Consumer<T>... actions) throws NullPointerException {
return peek(Stream.of(actions).reduce(Consumer::andThen).orElseGet(() -> o -> {
}));
public final Opt<T> ifPresents(final SerConsumer<T>... actions) throws NullPointerException {
return ifPresent(Stream.of(actions).reduce(SerConsumer::andThen).orElseGet(() -> o -> {}));
}
/**
@ -398,7 +372,7 @@ public class Opt<T> {
* @return 如果包裹里元素的值存在就返回本身如果不存在则使用传入的函数执行后获得的 {@code Opt}
* @throws NullPointerException 如果传入的操作为空或者传入的操作执行后返回值为空则抛出 {@code NPE}
*/
public Opt<T> or(final Supplier<? extends Opt<? extends T>> supplier) {
public Opt<T> or(final SerSupplier<? extends Opt<? extends T>> supplier) {
Objects.requireNonNull(supplier);
if (isPresent()) {
return this;
@ -456,7 +430,7 @@ public class Opt<T> {
* @return 如果包裹里元素的值存在则返回该值否则返回传入的操作执行后的返回值
* @throws NullPointerException 如果之不存在并且传入的操作为空则抛出 {@code NPE}
*/
public T orElseGet(final Supplier<? extends T> supplier) {
public T orElseGet(final SerSupplier<? extends T> supplier) {
return isPresent() ? value : supplier.get();
}
@ -467,7 +441,7 @@ public class Opt<T> {
* @return 如果包裹里元素的值存在则返回该值否则返回传入的操作执行后的返回值
* @throws NullPointerException 如果之不存在并且传入的操作为空则抛出 {@code NPE}
*/
public Opt<T> orElseOpt(final Supplier<? extends T> supplier) {
public Opt<T> orElseOpt(final SerSupplier<? extends T> supplier) {
return or(() -> ofNullable(supplier.get()));
}
@ -507,7 +481,7 @@ public class Opt<T> {
* @throws X 如果值不存在
* @throws NullPointerException 如果值不存在并且 传入的操作为 {@code null}或者操作执行后的返回值为{@code null}
*/
public <X extends Throwable> T orElseThrow(final Supplier<? extends X> exceptionSupplier) throws X {
public <X extends Throwable> T orElseThrow(final SerSupplier<? extends X> exceptionSupplier) throws X {
if (isPresent()) {
return value;
} else {
@ -581,4 +555,17 @@ public class Opt<T> {
public String toString() {
return StrUtil.toStringOrNull(value);
}
/**
* 创建空的带异常的Opt
*
* @param throwable 异常
* @param <T> 类型
* @return Opt
*/
private static <T> Opt<T> createError(final Throwable throwable) {
final Opt<T> emptyWithError = new Opt<>(null);
emptyWithError.throwable = throwable;
return emptyWithError;
}
}

View File

@ -16,6 +16,7 @@
package org.dromara.hutool.core.lang.range;
import org.dromara.hutool.core.func.SerPredicate;
import org.dromara.hutool.core.lang.Assert;
import java.util.Objects;
@ -60,7 +61,8 @@ import java.util.function.Predicate;
* @see Bound
* @since 6.0.0
*/
public class BoundedRange<T extends Comparable<? super T>> implements Predicate<T> {
public class BoundedRange<T extends Comparable<? super T>> implements SerPredicate<T> {
private static final long serialVersionUID = 1L;
/**
* 双向无界的区间
@ -432,7 +434,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @return 是否
*/
@Override
public boolean test(final T value) {
public boolean testing(final T value) {
return getLowerBound()
.and(getUpperBound())
.test(value);

View File

@ -24,8 +24,9 @@ import java.io.Serializable;
* <ul>
* <li>{@link #borrowObject()} 对象借出</li>
* <li>{@link #returnObject(Poolable)}对象归还</li>
* <li>{@link #free(Poolable)} 对象销毁</li>
* </ul>
*
* <p>
* 对于对象池中对象维护通过{@link PoolConfig#getMaxIdle()}控制规则如下
* <ul>
* <li>如果借出量很多则不断扩容直到达到{@link PoolConfig#getMaxSize()}</li>
@ -49,7 +50,7 @@ public interface ObjectPool<T> extends Closeable, Serializable {
*
* @return 对象
*/
Poolable<T> borrowObject();
T borrowObject();
/**
* 归还对象流程如下
@ -62,7 +63,15 @@ public interface ObjectPool<T> extends Closeable, Serializable {
* @param obj 对象
* @return this
*/
ObjectPool<T> returnObject(final Poolable<T> obj);
ObjectPool<T> returnObject(final T obj);
/**
* 释放对象即在使用中发现对象损坏或不可用则直接销毁之
*
* @param obj 对象
* @return this
*/
ObjectPool<T> free(final T obj);
/**
* 获取持有对象总数包括空闲对象 + 正在使用对象数

View File

@ -27,16 +27,26 @@ import org.dromara.hutool.core.lang.wrapper.Wrapper;
public interface Poolable<T> extends Wrapper<T> {
/**
* 获取最后借出时间
* 获取对象空闲时长单位毫秒<br>
* 空闲时间指在池中的时间即借出时间到上次归还时间的差
*
* @return 空闲毫秒数
*/
default long getIdle() {
return System.currentTimeMillis() - getLastReturn();
}
/**
* 获取最后归还时间
*
* @return 最后借出时间
*/
long getLastBorrow();
long getLastReturn();
/**
* 设置最后借出时间在成功借出此对象时更新时间
* 设置最后归还时间在成功归还此对象时更新时间
*
* @param lastBorrow 最后借出时间
* @param lastReturn 最后归还时间
*/
void setLastBorrow(final long lastBorrow);
void setLastReturn(final long lastReturn);
}

View File

@ -92,18 +92,25 @@ public class PartitionObjectPool<T> implements ObjectPool<T> {
}
@Override
public Poolable<T> borrowObject() {
public T borrowObject() {
checkClosed();
return this.partitions[getPartitionIndex(this.config)].borrowObject();
}
@Override
public PartitionObjectPool<T> returnObject(final Poolable<T> obj) {
public PartitionObjectPool<T> returnObject(final T obj) {
checkClosed();
this.partitions[getPartitionIndex(this.config)].returnObject(obj);
return this;
}
@Override
public ObjectPool<T> free(final T obj) {
checkClosed();
this.partitions[getPartitionIndex(this.config)].free(obj);
return this;
}
@Override
public void close() throws IOException {
this.closed = true;

View File

@ -50,16 +50,16 @@ public class PartitionPoolable<T> implements Poolable<T> {
* 归还对象
*/
public void returnObject() {
this.partition.returnObject(this);
this.partition.returnObject(this.getRaw());
}
@Override
public long getLastBorrow() {
public long getLastReturn() {
return lastBorrow;
}
@Override
public void setLastBorrow(final long lastBorrow) {
this.lastBorrow = lastBorrow;
public void setLastReturn(final long lastReturn) {
this.lastBorrow = lastReturn;
}
}

View File

@ -28,7 +28,7 @@ import java.util.concurrent.TimeUnit;
* 初始化时创建{@link PoolConfig#getMinSize()}个对象作为初始池对象.
*
* <p>
* 当借出对象时从队列头部取出并验证验证通过后使用验证不通过直接调用{@link #free(Poolable)} 销毁并重新获取
* 当借出对象时从队列头部取出并验证验证通过后使用验证不通过直接调用{@link #free(Object)} 销毁并重新获取
* 当池中对象都被借出空了创建新的对象并入队列直到队列满为止当满时等待归还超时则报错
* </p>
*
@ -64,36 +64,33 @@ public class PoolPartition<T> implements ObjectPool<T> {
this.queue = queue;
this.objectFactory = objectFactory;
final int minSize = config.getMinSize();
for (int i = 0; i < minSize; i++) {
queue.add(createPoolable());
}
total = minSize;
// 初始化按照配置最小大小创建对象
doIncrease(config.getMinSize());
}
@SuppressWarnings("resource")
@Override
public Poolable<T> borrowObject() {
public T borrowObject() {
// 非阻塞获取
Poolable<T> poolable = this.queue.poll();
if (null != poolable) {
final T obj = poolable.getRaw();
// 检查对象是否可用
if (this.objectFactory.validate(poolable.getRaw())) {
if (this.objectFactory.validate(obj)) {
// 检查是否超过最长空闲时间
final long maxIdle = this.config.getMaxIdle();
if (maxIdle <= 0 || (System.currentTimeMillis() - poolable.getLastBorrow()) <= maxIdle) {
poolable.setLastBorrow(System.currentTimeMillis());
return poolable;
if (maxIdle <= 0 || poolable.getIdle() <= maxIdle) {
return poolable.getRaw();
}
}
// 对象不可用销毁之
free(poolable);
// 对象不可用或超过最长空闲期销毁之
free(obj);
// 继续借而不扩容
return borrowObject();
}
// 扩容
// 池中无对象扩容
if (increase(1) <= 0) {
// 池分区已满只能等待是否有返还的对象
poolable = waitingPoll();
@ -111,22 +108,22 @@ public class PoolPartition<T> implements ObjectPool<T> {
/**
* 归还对象
*
* @param poolable 归还的对象
* @param obj 归还的对象
* @return this
*/
@SuppressWarnings("resource")
@Override
public PoolPartition<T> returnObject(final Poolable<T> poolable) {
public PoolPartition<T> returnObject(final T obj) {
// 检查对象可用性
if (this.objectFactory.validate(poolable.getRaw())) {
if (this.objectFactory.validate(obj)) {
try {
this.queue.put(poolable);
this.queue.put(wrapPoolable(obj));
} catch (final InterruptedException e) {
throw new PoolException(e);
}
} else {
// 对象不可用
free(poolable);
free(obj);
}
return this;
@ -139,20 +136,8 @@ public class PoolPartition<T> implements ObjectPool<T> {
* @param increaseSize 扩容大小
* @return 实际扩容大小0表示已经达到最大未成功扩容
*/
public synchronized int increase(int increaseSize) {
if (increaseSize + total > config.getMaxSize()) {
increaseSize = config.getMaxSize() - total;
}
try {
for (int i = 0; i < increaseSize; i++) {
queue.put(createPoolable());
}
total += increaseSize;
} catch (final InterruptedException e) {
throw new PoolException(e);
}
return increaseSize;
public synchronized int increase(final int increaseSize) {
return doIncrease(increaseSize);
}
/**
@ -161,8 +146,9 @@ public class PoolPartition<T> implements ObjectPool<T> {
* @param obj 被销毁的对象
* @return this
*/
public synchronized PoolPartition<T> free(final Poolable<T> obj) {
objectFactory.destroy(obj.getRaw());
@Override
public synchronized PoolPartition<T> free(final T obj) {
objectFactory.destroy(obj);
total--;
return this;
}
@ -183,10 +169,11 @@ public class PoolPartition<T> implements ObjectPool<T> {
}
@Override
public void close() throws IOException {
this.queue.forEach(this::free);
synchronized public void close() throws IOException {
this.queue.forEach((poolable) -> objectFactory.destroy(poolable.getRaw()));
this.queue.clear();
this.queue = null;
this.total = 0;
}
/**
@ -194,13 +181,45 @@ public class PoolPartition<T> implements ObjectPool<T> {
*
* @return {@link PartitionPoolable}
*/
@SuppressWarnings("unchecked")
protected Poolable<T> createPoolable() {
final T t = objectFactory.create();
return null == t ? null : wrapPoolable(t);
}
@SuppressWarnings("unchecked")
private Poolable<T> wrapPoolable(final T t) {
if (t instanceof Poolable) {
return (Poolable<T>) t;
}
return new PartitionPoolable<>(objectFactory.create(), this);
return new PartitionPoolable<>(t, this);
}
/**
* 非线程安全的扩容并填充对象池队列<br>
* 如果传入的扩容大小大于可用大小即扩容大小加现有大小大于最大大小则实际扩容到最大
*
* @param increaseSize 扩容大小
* @return 实际扩容大小0表示已经达到最大未成功扩容
*/
private int doIncrease(int increaseSize) {
final int maxSize = config.getMaxSize();
if (increaseSize + total > maxSize) {
increaseSize = maxSize - total;
}
try {
Poolable<T> poolable;
for (int i = 0; i < increaseSize; i++) {
poolable = createPoolable();
if(null != poolable){
queue.put(poolable);
}
}
total += increaseSize;
} catch (final InterruptedException e) {
throw new PoolException(e);
}
return increaseSize;
}
/**

View File

@ -16,9 +16,8 @@
package org.dromara.hutool.core.stream;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.text.StrUtil;
import java.util.*;
import java.util.function.*;
@ -112,7 +111,7 @@ public class CollectorUtil {
final Supplier<A> downstreamSupplier = downstream.supplier();
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
final BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
final K key = Opt.ofNullable(t).map(classifier).orElse(null);
final K key = Optional.ofNullable(t).map(classifier).orElse(null);
final A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
if (ArrayUtil.isArray(container) || Objects.nonNull(t)) {
// 如果是数组类型不需要判空场景分组后需要使用java.util.unwrap.Collectors.counting 求null元素个数
@ -288,7 +287,8 @@ public class CollectorUtil {
final BinaryOperator<U> mergeFunction,
final Supplier<M> mapSupplier) {
final BiConsumer<M, T> accumulator
= (map, element) -> map.put(Opt.ofNullable(element).map(keyMapper).get(), Opt.ofNullable(element).map(valueMapper).get());
= (map, element) -> map.put(Optional.ofNullable(element).map(keyMapper).orElse(null),
Optional.ofNullable(element).map(valueMapper).orElse(null));
return new SimpleCollector<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
@ -464,7 +464,7 @@ public class CollectorUtil {
final Collector<? super T, A, R> downstream) {
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
return new SimpleCollector<>(downstream.supplier(),
(r, t) -> Opt.of(t).filter(predicate).ifPresent(e -> downstreamAccumulator.accept(r, e)),
(r, t) -> Optional.of(t).filter(predicate).ifPresent(e -> downstreamAccumulator.accept(r, e)),
downstream.combiner(), downstream.finisher(),
downstream.characteristics());
}

View File

@ -197,7 +197,7 @@ public class BeanTree<T, R extends Comparable<R>> {
final Predicate<T> recursive = SerPredicate.multiOr(condition::test,
e -> Opt.ofEmptyAble(childrenGetter.apply(e))
.map(children -> EasyStream.of(children).filter(recursiveRef.get()).toList())
.peek(children -> childrenSetter.accept(e, children))
.ifPresent(children -> childrenSetter.accept(e, children))
.filter(s -> !s.isEmpty()).isPresent());
recursiveRef.set(recursive);
return EasyStream.of(tree).filter(recursive).toList();
@ -215,7 +215,7 @@ public class BeanTree<T, R extends Comparable<R>> {
final AtomicReference<Consumer<T>> recursiveRef = new AtomicReference<>();
final Consumer<T> recursive = SerConsumer.multi(action::accept,
e -> Opt.ofEmptyAble(childrenGetter.apply(e))
.peek(children -> EasyStream.of(children).forEach(recursiveRef.get())));
.ifPresent(children -> EasyStream.of(children).forEach(recursiveRef.get())));
recursiveRef.set(recursive);
EasyStream.of(tree).forEach(recursive);
return tree;

View File

@ -72,23 +72,23 @@ public class OptTest {
public void peekTest() {
final User user = new User();
// 相当于ifPresent的链式调用
Opt.ofNullable("hutool").peek(user::setUsername).peek(user::setNickname);
Opt.ofNullable("hutool").ifPresent(user::setUsername).ifPresent(user::setNickname);
Assertions.assertEquals("hutool", user.getNickname());
Assertions.assertEquals("hutool", user.getUsername());
// 注意传入的lambda中对包裹内的元素执行赋值操作并不会影响到原来的元素
final String name = Opt.ofNullable("hutool").peek(username -> username = "123").peek(username -> username = "456").get();
final String name = Opt.ofNullable("hutool").ifPresent(username -> username = "123").ifPresent(username -> username = "456").get();
Assertions.assertEquals("hutool", name);
}
@Test
public void peeksTest() {
public void ifPresentsTest() {
final User user = new User();
// 相当于上面peek的动态参数调用更加灵活你可以像操作数组一样去动态设置中间的步骤也可以使用这种方式去编写你的代码
// 可以一行搞定
Opt.ofNullable("hutool").peeks(user::setUsername, user::setNickname);
Opt.ofNullable("hutool").ifPresents(user::setUsername, user::setNickname);
// 也可以在适当的地方换行使得代码的可读性提高
Opt.of(user).peeks(
Opt.of(user).ifPresents(
u -> Assertions.assertEquals("hutool", u.getNickname()),
u -> Assertions.assertEquals("hutool", u.getUsername())
);
@ -97,14 +97,14 @@ public class OptTest {
// 注意传入的lambda中对包裹内的元素执行赋值操作并不会影响到原来的元素,这是java语言的特性
// 这也是为什么我们需要getter和setter而不直接给bean中的属性赋值中的其中一个原因
final String name = Opt.ofNullable("hutool").peeks(
final String name = Opt.ofNullable("hutool").ifPresents(
username -> username = "123", username -> username = "456",
n -> Assertions.assertEquals("hutool", n)).get();
Assertions.assertEquals("hutool", name);
// 当然以下情况不会抛出NPE但也没什么意义
Opt.ofNullable("hutool").peeks().peeks().peeks();
Opt.ofNullable(null).peeks(i -> {
Opt.ofNullable("hutool").ifPresents().ifPresents().ifPresents();
Opt.ofNullable(null).ifPresents(i -> {
});
}
@ -254,7 +254,6 @@ public class OptTest {
Assertions.assertEquals(i, 1);
}
@SuppressWarnings({"NumericOverflow", "divzero"})
@Test
@Disabled
void testToEasyStream() {

View File

@ -56,8 +56,8 @@ public class PartitionObjectPoolTest {
Assertions.assertEquals(4, pool.getTotal());
for (int i = 0; i < 20; i++) {
final Poolable<StringBuilder> obj = pool.borrowObject();
obj.getRaw().append("hutool");
final StringBuilder obj = pool.borrowObject();
obj.append("hutool");
}
// 池1的2个+池2借出的20个合计22个
Assertions.assertEquals(22, pool.getTotal());
@ -73,10 +73,10 @@ public class PartitionObjectPoolTest {
// 初始4个对象
Assertions.assertEquals(4, pool.getTotal());
final ArrayList<Poolable<StringBuilder>> borrowed = ListUtil.of();
final ArrayList<StringBuilder> borrowed = ListUtil.of();
for (int i = 0; i < 10; i++) {
final Poolable<StringBuilder> obj = pool.borrowObject();
obj.getRaw().append("hutool");
final StringBuilder obj = pool.borrowObject();
obj.append("hutool");
borrowed.add(obj);
}
// 池1的2个+池2借出的10个合计12个
@ -85,7 +85,7 @@ public class PartitionObjectPoolTest {
Assertions.assertEquals(2, pool.getIdleCount());
// 全部归还
for (final Poolable<StringBuilder> obj : borrowed) {
for (final StringBuilder obj : borrowed) {
pool.returnObject(obj);
}

View File

@ -98,12 +98,12 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
}
@Override
public long getLastBorrow() {
public long getLastReturn() {
return lastBorrow;
}
@Override
public void setLastBorrow(final long lastBorrow) {
this.lastBorrow = lastBorrow;
public void setLastReturn(final long lastReturn) {
this.lastBorrow = lastReturn;
}
}