!981 【6.x】为 Mutable 补充测试用例,与针对基础数据类型的工厂方法及接口默认方法

Merge pull request !981 from Createsequence/v6-mutable-opt
This commit is contained in:
Looly 2023-04-27 04:07:08 +00:00 committed by Gitee
commit 0aa0bdfda4
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 671 additions and 2 deletions

View File

@ -12,14 +12,110 @@
package org.dromara.hutool.core.lang.mutable; package org.dromara.hutool.core.lang.mutable;
import org.dromara.hutool.core.lang.Opt;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/** /**
* 提供可变值类型接口 * <p>提供可变值类型接口 <br />
*
* 相较于{@link Opt}{@link java.util.Optional}该所有实现类中的方法都<b>不区分值是否为{@code null}</b>
* 因此在使用前需要自行判断值是否为{@code null}
* 确保不会因为{@code null}值而抛出{@link NullPointerException}的情况
* *
* @param <T> 值得类型 * @param <T> 值得类型
* @since 3.0.1 * @since 3.0.1
*/ */
public interface Mutable<T> { public interface Mutable<T> {
// ==================== factory methods ====================
/**
* 创建一个{@link MutableBool}对象
*
* @param value
* @return {@link MutableBool}
*/
static MutableBool of(final boolean value) {
return new MutableBool(value);
}
/**
* 创建一个{@link MutableByte}对象
*
* @param value
* @return {@link MutableByte}
*/
static MutableByte of(final byte value) {
return new MutableByte(value);
}
/**
* 创建一个{@link MutableFloat}对象
*
* @param value
* @return {@link MutableFloat}
*/
static MutableFloat of(final float value) {
return new MutableFloat(value);
}
/**
* 创建一个{@link MutableInt}对象
*
* @param value
* @return {@link MutableInt}
*/
static MutableInt of(final int value) {
return new MutableInt(value);
}
/**
* 创建一个{@link MutableLong}对象
*
* @param value
* @return {@link MutableLong}
*/
static MutableLong of(final long value) {
return new MutableLong(value);
}
/**
* 创建一个{@link MutableDouble}对象
*
* @param value
* @return {@link MutableDouble}
*/
static MutableDouble of(final double value) {
return new MutableDouble(value);
}
/**
* 创建一个{@link MutableShort}对象
*
* @param value
* @return {@link MutableShort}
*/
static MutableShort of(final short value) {
return new MutableShort(value);
}
/**
* 创建一个{@link MutableObj}对象
*
* @param value
* @return {@link MutableObj}
*/
static <T> MutableObj<T> of(final T value) {
return new MutableObj<>(value);
}
// ==================== base methods ====================
/** /**
* 获得原始值 * 获得原始值
* @return 原始值 * @return 原始值
@ -32,4 +128,57 @@ public interface Mutable<T> {
*/ */
void set(T value); void set(T value);
/**
* 根据操作修改值
*
* @param operator 操作
* @return
*/
default Mutable<T> map(final UnaryOperator<T> operator) {
set(operator.apply(get()));
return this;
}
/**
* 检查并操作值
*
* @param consumer 操作
* @return 当前对象
*/
default Mutable<T> peek(final Consumer<T> consumer) {
consumer.accept(get());
return this;
}
/**
* 检查值是否满足条件
*
* @param predicate 条件
* @return 是否满足条件
*/
default boolean test(final Predicate<T> predicate) {
return predicate.test(get());
}
/**
* 获取值并将值转换为{@link Opt}
*
* @return {@link Opt}
*/
default Opt<T> toOpt() {
return to(Opt::ofNullable);
}
/**
* 获取值并将值转换为指定类型<br>
* 注意值为null时转换函数依然会被调用
*
* @param function 转换函数
* @param <R> 转换后的类型
* @return 转换后的值
*/
default <R> R to(final Function<T, R> function) {
Objects.requireNonNull(function);
return function.apply(get());
}
} }

View File

@ -15,6 +15,7 @@ package org.dromara.hutool.core.lang.mutable;
import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.core.util.ObjUtil;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects;
/** /**
* 可变{@code Object} * 可变{@code Object}
@ -82,7 +83,7 @@ public class MutableObj<T> implements Mutable<T>, Serializable{
@Override @Override
public int hashCode() { public int hashCode() {
return value == null ? 0 : value.hashCode(); return Objects.hashCode(value);
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------

View File

@ -0,0 +1,129 @@
package org.dromara.hutool.core.lang.mutable;
import org.dromara.hutool.core.text.StrValidator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Objects;
/**
* base test for {@link Mutable} implementations.
*
* @author huangchengxing
*/
abstract class BaseMutableTest<V, M extends Mutable<V>> {
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
abstract V getValue1();
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
abstract V getValue2();
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
abstract M getMutable(V value);
@Test
void testOf() {
Assertions.assertInstanceOf(MutableBool.class, Mutable.of(true));
Assertions.assertInstanceOf(MutableByte.class, Mutable.of((byte) 1));
Assertions.assertInstanceOf(MutableDouble.class, Mutable.of(1.0D));
Assertions.assertInstanceOf(MutableFloat.class, Mutable.of(1.0F));
Assertions.assertInstanceOf(MutableInt.class, Mutable.of(1));
Assertions.assertInstanceOf(MutableLong.class, Mutable.of(1L));
Assertions.assertInstanceOf(MutableObj.class, Mutable.of(new Object()));
Assertions.assertInstanceOf(MutableShort.class, Mutable.of((short) 1));
}
@Test
void testGet() {
Mutable<V> mutableObj = getMutable(getValue1());
V value = mutableObj.get();
Assertions.assertEquals(getValue1(), value);
}
@Test
void testSet() {
Mutable<V> mutableObj = getMutable(getValue2());
mutableObj.set(getValue2());
V value = mutableObj.get();
Assertions.assertEquals(getValue2(), value);
}
@Test
void testTo() {
Mutable<V> mutableObj = getMutable(getValue1());
String value = mutableObj.to(String::valueOf);
Assertions.assertEquals(String.valueOf(getValue1()), value);
}
@Test
void testToOpt() {
Mutable<V> mutableObj = getMutable(getValue1());
V value = mutableObj.toOpt().get();
Assertions.assertEquals(getValue1(), value);
}
@Test
void testMap() {
Mutable<V> mutableObj = getMutable(getValue1());
V value = mutableObj.map(v -> getValue2()).get();
Assertions.assertEquals(getValue2(), value);
}
@Test
void testTest() {
Mutable<V> mutableObj = getMutable(getValue1());
Assertions.assertTrue(mutableObj.test(Objects::nonNull));
}
@Test
void testPeek() {
Mutable<V> m1 = getMutable(getValue1());
Mutable<V> m2 = getMutable(getValue2());
m1.peek(m2::set);
Assertions.assertEquals(getValue1(), m2.get());
}
@Test
void testHashCode() {
V value = getValue1();
Mutable<V> mutableObj = new MutableObj<>(value);
Assertions.assertEquals(value.hashCode(), mutableObj.hashCode());
mutableObj.set(null);
Assertions.assertEquals(0, mutableObj.hashCode());
}
@Test
void testEquals() {
V value = getValue1();
Mutable<V> mutableObj = new MutableObj<>(value);
Assertions.assertNotEquals(value, mutableObj);
Assertions.assertEquals(mutableObj, mutableObj);
Assertions.assertEquals(mutableObj, new MutableObj<>(value));
Assertions.assertNotEquals(mutableObj, new MutableObj<>(null));
Assertions.assertNotEquals(mutableObj, null);
Assertions.assertNotEquals(mutableObj, value);
}
@Test
void testToString() {
V value = getValue1();
Mutable<V> mutableObj = new MutableObj<>(value);
Assertions.assertEquals(value.toString(), mutableObj.toString());
mutableObj.set(null);
Assertions.assertEquals(StrValidator.NULL, mutableObj.toString());
}
}

View File

@ -0,0 +1,40 @@
package org.dromara.hutool.core.lang.mutable;
/**
* test for {@link MutableBool}
*
* @author huangchengxing
*/
public class MutableBoolTest extends BaseMutableTest<Boolean, MutableBool> {
/**
* 创建一个值
*
* @return
*/
@Override
Boolean getValue1() {
return Boolean.TRUE;
}
/**
* 创建一个值
*
* @return
*/
@Override
Boolean getValue2() {
return Boolean.FALSE;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableBool getMutable(Boolean value) {
return new MutableBool(value);
}
}

View File

@ -0,0 +1,38 @@
package org.dromara.hutool.core.lang.mutable;
/**
* @author huangchengxing
*/
public class MutableByteTest extends BaseMutableTest<Number, MutableByte> {
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue1() {
return Byte.MAX_VALUE;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue2() {
return Byte.MIN_VALUE;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableByte getMutable(Number value) {
return new MutableByte(value);
}
}

View File

@ -0,0 +1,38 @@
package org.dromara.hutool.core.lang.mutable;
/**
* @author huangchengxing
*/
public class MutableDoubleTest extends BaseMutableTest<Number, MutableDouble> {
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue1() {
return Double.MAX_VALUE;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue2() {
return Double.MAX_VALUE;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableDouble getMutable(Number value) {
return new MutableDouble(value);
}
}

View File

@ -0,0 +1,45 @@
package org.dromara.hutool.core.lang.mutable;
import org.dromara.hutool.core.map.MapUtil;
import java.util.Map;
/**
* @author huangchengxing
*/
public class MutableEntryTest extends BaseMutableTest<Map.Entry<String, String>, MutableEntry<String, String>> {
private static final Map.Entry<String, String> ENTRY1 = MapUtil.entry("key1", "value1");
private static final Map.Entry<String, String> ENTRY2 = MapUtil.entry("key2", "value2");
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Map.Entry<String, String> getValue1() {
return ENTRY1;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Map.Entry<String, String> getValue2() {
return ENTRY2;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableEntry<String, String> getMutable(Map.Entry<String, String> value) {
return new MutableEntry<>(value.getKey(), value.getValue());
}
}

View File

@ -0,0 +1,37 @@
package org.dromara.hutool.core.lang.mutable;
/**
* @author huangchengxing
*/
public class MutableFloatTest extends BaseMutableTest<Number, MutableFloat> {
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue1() {
return Float.MAX_VALUE;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue2() {
return Float.MIN_VALUE;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableFloat getMutable(Number value) {
return new MutableFloat(value);
}
}

View File

@ -0,0 +1,37 @@
package org.dromara.hutool.core.lang.mutable;
/**
* @author huangchengxing
*/
public class MutableIntTest extends BaseMutableTest<Number, MutableInt> {
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue1() {
return Integer.MAX_VALUE;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue2() {
return Integer.MIN_VALUE;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableInt getMutable(Number value) {
return new MutableInt(value);
}
}

View File

@ -0,0 +1,37 @@
package org.dromara.hutool.core.lang.mutable;
/**
* @author huangchengxing
*/
public class MutableLongTest extends BaseMutableTest<Number, MutableLong> {
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue1() {
return Long.MAX_VALUE;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue2() {
return Long.MIN_VALUE;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableLong getMutable(Number value) {
return new MutableLong(value);
}
}

View File

@ -0,0 +1,40 @@
package org.dromara.hutool.core.lang.mutable;
/**
* test for {@link MutableObj}
*
* @author huangchengxing
*/
class MutableObjTest extends BaseMutableTest<String, MutableObj<String>> {
/**
* 创建一个值
*
* @return
*/
@Override
String getValue1() {
return "test1";
}
/**
* 创建一个值
*
* @return
*/
@Override
String getValue2() {
return "test2";
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableObj<String> getMutable(String value) {
return new MutableObj<>(value);
}
}

View File

@ -0,0 +1,37 @@
package org.dromara.hutool.core.lang.mutable;
/**
* @author huangchengxing
*/
public class MutableShortTest extends BaseMutableTest<Number, MutableShort> {
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue1() {
return Short.MAX_VALUE;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
Number getValue2() {
return Short.MIN_VALUE;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableShort getMutable(Number value) {
return new MutableShort(value);
}
}

View File

@ -0,0 +1,41 @@
package org.dromara.hutool.core.lang.mutable;
/**
* @author huangchengxing
*/
public class MutableTripleTest extends BaseMutableTest<MutableTriple<String, String, String>, MutableTriple<String, String, String>> {
private static final MutableTriple<String, String, String> VALUE1 = new MutableTriple<>("1", "2", "3");
private static final MutableTriple<String, String, String> VALUE2 = new MutableTriple<>("4", "5", "6");
/**
* 创建一个值且反复调用应该返回完全相同的值
*
* @return
*/
@Override
MutableTriple<String, String, String> getValue1() {
return VALUE1;
}
/**
* 创建一个值{@link #getValue1()}不同且反复调用应该返回完全相同的值
*
* @return
*/
@Override
MutableTriple<String, String, String> getValue2() {
return VALUE2;
}
/**
* 创建一个{@link Mutable}
*
* @param value
* @return
*/
@Override
MutableTriple<String, String, String> getMutable(MutableTriple<String, String, String> value) {
return new MutableTriple<>(value.getLeft(), value.getMiddle(), value.getRight());
}
}