7 Commits

19 changed files with 465 additions and 19 deletions

View File

@@ -18,10 +18,11 @@ package xyz.zhouxy.plusone.commons.base;
import com.google.common.annotations.Beta;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.function.BoolUnaryOperator;
@Beta
public class BoolRef {
public final class BoolRef {
private boolean value;
@@ -29,6 +30,11 @@ public class BoolRef {
this.value = value;
}
@StaticFactoryMethod(BoolRef.class)
public static BoolRef of(boolean value) {
return new BoolRef(value);
}
public boolean getValue() {
return value;
}
@@ -37,10 +43,18 @@ public class BoolRef {
this.value = value;
}
public void apply(BoolUnaryOperator operator) {
public void transformValue(BoolUnaryOperator operator) {
this.value = operator.applyAsBool(this.value);
}
public boolean isTrue() {
return getValue();
}
public boolean isFalse() {
return !value;
}
@Override
public String toString() {
return String.format("BoolRef[%s]", value);

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2024 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.base;
import com.google.common.annotations.Beta;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.function.ByteUnaryOperator;
@Beta
public final class ByteRef {
private byte value;
public ByteRef(byte value) {
this.value = value;
}
@StaticFactoryMethod(ByteRef.class)
public static ByteRef of(byte value) {
return new ByteRef(value);
}
public byte getValue() {
return value;
}
public void setValue(byte value) {
this.value = value;
}
public void transformValue(ByteUnaryOperator operator) {
this.value = operator.applyAsByte(this.value);
}
@Override
public String toString() {
return String.format("BoolRef[%s]", value);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + value;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ByteRef other = (ByteRef) obj;
return value == other.value;
}
}

View File

@@ -18,10 +18,11 @@ package xyz.zhouxy.plusone.commons.base;
import com.google.common.annotations.Beta;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.function.CharUnaryOperator;
@Beta
public class CharRef {
public final class CharRef {
private char value;
@@ -29,6 +30,11 @@ public class CharRef {
this.value = value;
}
@StaticFactoryMethod(CharRef.class)
public static CharRef of(char value) {
return new CharRef(value);
}
public char getValue() {
return value;
}
@@ -37,7 +43,7 @@ public class CharRef {
this.value = value;
}
public void apply(CharUnaryOperator operator) {
public void transformValue(CharUnaryOperator operator) {
this.value = operator.applyAsChar(this.value);
}

View File

@@ -16,12 +16,15 @@
package xyz.zhouxy.plusone.commons.base;
import java.util.function.DoublePredicate;
import java.util.function.DoubleUnaryOperator;
import com.google.common.annotations.Beta;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
@Beta
public class DoubleRef {
public final class DoubleRef {
private double value;
@@ -29,6 +32,11 @@ public class DoubleRef {
this.value = value;
}
@StaticFactoryMethod(DoubleRef.class)
public static DoubleRef of(double value) {
return new DoubleRef(value);
}
public double getValue() {
return value;
}
@@ -37,10 +45,14 @@ public class DoubleRef {
this.value = value;
}
public void apply(DoubleUnaryOperator operator) {
public void transformValue(DoubleUnaryOperator operator) {
this.value = operator.applyAsDouble(this.value);
}
public boolean checkValue(DoublePredicate predicate) {
return predicate.test(this.value);
}
@Override
public String toString() {
return String.format("DoubleRef[%s]", value);

View File

@@ -16,12 +16,15 @@
package xyz.zhouxy.plusone.commons.base;
import java.util.function.IntPredicate;
import java.util.function.IntUnaryOperator;
import com.google.common.annotations.Beta;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
@Beta
public class IntRef {
public final class IntRef {
private int value;
@@ -29,6 +32,11 @@ public class IntRef {
this.value = value;
}
@StaticFactoryMethod(IntRef.class)
public static IntRef of(int value) {
return new IntRef(value);
}
public int getValue() {
return value;
}
@@ -37,10 +45,14 @@ public class IntRef {
this.value = value;
}
public void apply(IntUnaryOperator operator) {
public void transformValue(IntUnaryOperator operator) {
this.value = operator.applyAsInt(this.value);
}
public boolean checkValue(IntPredicate predicate) {
return predicate.test(this.value);
}
@Override
public String toString() {
return String.format("IntRef[%s]", value);

View File

@@ -16,12 +16,15 @@
package xyz.zhouxy.plusone.commons.base;
import java.util.function.LongPredicate;
import java.util.function.LongUnaryOperator;
import com.google.common.annotations.Beta;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
@Beta
public class LongRef {
public final class LongRef {
private long value;
@@ -29,6 +32,11 @@ public class LongRef {
this.value = value;
}
@StaticFactoryMethod(LongRef.class)
public static LongRef of(long value) {
return new LongRef(value);
}
public long getValue() {
return value;
}
@@ -37,10 +45,14 @@ public class LongRef {
this.value = value;
}
public void apply(LongUnaryOperator operator) {
public void transformValue(LongUnaryOperator operator) {
this.value = operator.applyAsLong(this.value);
}
public boolean checkValue(LongPredicate predicate) {
return predicate.test(this.value);
}
@Override
public String toString() {
return String.format("LongRef[%s]", value);

View File

@@ -18,10 +18,14 @@ package xyz.zhouxy.plusone.commons.base;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import com.google.common.annotations.Beta;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
@Beta
public final class Ref<T> {
@@ -35,6 +39,16 @@ public final class Ref<T> {
this.value = value;
}
@StaticFactoryMethod(Ref.class)
public static <T> Ref<T> of() {
return new Ref<>();
}
@StaticFactoryMethod(Ref.class)
public static <T> Ref<T> of(T value) {
return new Ref<>(value);
}
public T getValue() {
return value;
}
@@ -43,10 +57,22 @@ public final class Ref<T> {
this.value = value;
}
public void transform(UnaryOperator<T> operator) {
public void transformValue(UnaryOperator<T> operator) {
this.value = operator.apply(this.value);
}
public <R> Ref<R> transform(Function<? super T, R> function) {
return Ref.of(function.apply(this.value));
}
public boolean checkValue(Predicate<? super T> predicate) {
return predicate.test(this.value);
}
public void execute(Consumer<? super T> consumer) {
consumer.accept(value);
}
public boolean isNull() {
return this.value == null;
}
@@ -55,10 +81,44 @@ public final class Ref<T> {
return this.value != null;
}
public void execute(Consumer<? super T> consumer) {
consumer.accept(value);
// ================================
// #region - from
// ================================
@StaticFactoryMethod(Ref.class)
public static Ref<Boolean> from(BoolRef boolRef) {
return new Ref<>(boolRef.getValue());
}
@StaticFactoryMethod(Ref.class)
public static Ref<Byte> from(ByteRef byteRef) {
return new Ref<>(byteRef.getValue());
}
@StaticFactoryMethod(Ref.class)
public static Ref<Character> from(CharRef charRef) {
return new Ref<>(charRef.getValue());
}
@StaticFactoryMethod(Ref.class)
public static Ref<Double> from(DoubleRef doubleRef) {
return new Ref<>(doubleRef.getValue());
}
@StaticFactoryMethod(Ref.class)
public static Ref<Integer> from(IntRef intRef) {
return new Ref<>(intRef.getValue());
}
@StaticFactoryMethod(Ref.class)
public static Ref<Long> from(LongRef longRef) {
return new Ref<>(longRef.getValue());
}
// ================================
// #endregion - from
// ================================
@Override
public String toString() {
return String.format("Ref[%s]", value);

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2024 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.
*/
/**
* 基础组件
*
* <h2>Ref</h2>
* <p>
* {@link Ref} 及相关的 {@link BoolRef}、{@link ByteRef}、{@link CharRef}、
* {@link DoubleRef}、{@link IntRef}、{@link LongRef} 包装了一个值,表示对该值的应用。
* </p>
* <p>灵感来自于 C# 的 {@value ref} 参数修饰符。C# 允许通过以下方式,将值返回给调用端:</p>
* <pre>
* void Method(ref int refArgument)
* {
* refArgument = refArgument + 44;
* }
*
* int number = 1;
* Method(ref number);
* Console.WriteLine(number); // Output: 45
* </pre>
* {@link Ref} 及各个 {@code XxxRef} 使 Java 可以达到类似的效果,如:
* <pre>
* void method(IntRef refArgument) {
* refArgument.apply(i -> i + 44);
* }
*
* IntRef number = IntRef.of(1);
* method(number);
* System.out.println(number.getValue()); // Output: 45
* </pre>
* <p>
* 当一个方法需要产生多个结果时,无法有多个返回值,可以使用 {@link Ref} 作为参数传入,方法内部修改 {@link Ref} 的值。
* 调用方在调用方法之后,使用 {@code getValue()} 获取结果。
* </p>
* <pre>
* String method(IntRef intRefArgument, Ref<String> strRefArgument) {
* intRefArgument.apply(i -> i + 44);
* strRefArgument.setValue("Hello " + strRefArgument.getValue());
* return "Return string";
* }
*
* IntRef number = IntRef.of(1);
* Ref<String> str = Ref.of("Java");
* String result = method(number, str);
* System.out.println(number.getValue()); // Output: 45
* System.out.println(str.getValue()); // Output: Hello Java
* System.out.println(result); // Output: Return string
* </pre>
*
* <h2>IWithCode</h2>
* <p>
* 类似于枚举之类的类,通常需要设置固定的码值表示对应的含义。
* 可实现 {@link IWithCode}、{@link IWithIntCode}、{@link IWithLongCode},便于在需要的地方对这些接口的实现进行处理。
* </p>
*
* <h2>JRE</h2>
* <p>
* {@link JRE} 可获取当前 Java 版本号
* </p>
*/
package xyz.zhouxy.plusone.commons.base;

View File

@@ -14,8 +14,9 @@
* limitations under the License.
*/
package xyz.zhouxy.plusone.commons.model;
package xyz.zhouxy.plusone.commons.constant;
import xyz.zhouxy.plusone.commons.base.IWithIntCode;
import xyz.zhouxy.plusone.commons.util.AssertTools;
/**
@@ -23,7 +24,7 @@ import xyz.zhouxy.plusone.commons.util.AssertTools;
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
*/
public enum Gender {
public enum Gender implements IWithIntCode {
UNKNOWN(0, "Unknown", "未知"),
MALE(1, "Male", ""),
FEMALE(2, "Female", ""),
@@ -52,6 +53,11 @@ public enum Gender {
return value;
}
@Override
public int getCode() {
return value;
}
public String getDisplayName() {
return displayName;
}

View File

@@ -21,9 +21,11 @@ import com.google.common.annotations.Beta;
@Beta
@FunctionalInterface
public interface BoolUnaryOperator {
boolean applyAsBool(boolean operand);
static BoolUnaryOperator not() {
return b -> !b;
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2024 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.function;
import com.google.common.annotations.Beta;
@Beta
@FunctionalInterface
public interface ByteUnaryOperator {
byte applyAsByte(byte operand);
}

View File

@@ -21,5 +21,7 @@ import com.google.common.annotations.Beta;
@Beta
@FunctionalInterface
public interface CharUnaryOperator {
char applyAsChar(char operand);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2024 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.function;
@FunctionalInterface
public interface ThrowingFunction<T, R, E extends Throwable> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t) throws E;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2024 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.
*/
/**
* 函数式编程
*
* <h2>PredicateTools</h2>
* <p>
* {@link PredicateTools} 用于 {@link java.util.function.Predicate} 的相关操作。
* </p>
*
* <h2>Functional interfaces</h2>
* <p>
* 补充一些 JDK 没有,而项目中可能用得上的函数式接口:
* <pre>
* | Group | FunctionalInterface | method |
* | ------------- | -------------------- | -------------------------------- |
* | UnaryOperator | BoolUnaryOperator | boolean applyAsBool (boolean) |
* | UnaryOperator | ByteUnaryOperator | byte applyAsByte(byte) |
* | UnaryOperator | CharUnaryOperator | char applyAsChar(char) |
* | Throwing | Executable | void execute() throws E |
* | Throwing | ThrowingConsumer | void accept(T) throws E |
* | Throwing | ThrowingFunction | R apply(T) throws E |
* | Throwing | ThrowingPredicate | boolean test(T) throws E |
* | Throwing | ThrowingSupplier | T get() throws E |
* | Optional | OptionalSupplier | Optional&lt;T&gt; get() throws E |
* | Optional | ToOptionalBiFunction | Optional&lt;R&gt; apply(T,U) |
* | Optional | ToOptionalFunction | Optional&lt;R&gt; apply(T) |
* </pre>
* </p>
*/
package xyz.zhouxy.plusone.commons.function;

View File

@@ -25,10 +25,14 @@ import java.util.regex.Pattern;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.Immutable;
import xyz.zhouxy.plusone.commons.constant.Gender;
/**
* 中国第二代居民身份证号
*/
@Immutable
public class Chinese2ndGenIDCardNumber extends IDCardNumber {
/** 省份编码 */

View File

@@ -23,6 +23,8 @@ import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.constant.Gender;
/**
* 身份证号
*/

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2024 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.util;
import com.google.common.annotations.Beta;
/**
* ByteArrayTools
*
* <p>byte 数组工具类
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
*/
@Beta
public class ByteArrayTools {
public static byte[] longToByteArray(long value) {
final byte[] bytes = new byte[8];
fillToByteArrayInternal(value, bytes, 0);
return bytes;
}
public static void fillToByteArray(long value, final byte[] bytes) {
AssertTools.checkArgument(bytes != null && bytes.length >= 8);
fillToByteArrayInternal(value, bytes, 0);
}
public static void fillToByteArray(long value, final byte[] bytes, int startIndex) {
AssertTools.checkArgument(bytes != null && bytes.length >= startIndex + 8);
fillToByteArrayInternal(value, bytes, startIndex);
}
private static void fillToByteArrayInternal(long value, final byte[] bytes, int startIndex) {
for (int i = 0; i < 8; i++) {
int offset = 8 * (7 - i);
bytes[startIndex + i] = (byte) ((value & (0xFFL << offset)) >> offset);
}
}
private ByteArrayTools() {
throw new IllegalStateException("Utility class");
}
}

View File

@@ -26,6 +26,7 @@ import java.util.regex.Matcher;
import org.junit.jupiter.api.Test;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.constant.Gender;
@Slf4j
public class Chinese2ndGenIDCardNumberTests {

View File

@@ -34,9 +34,12 @@ class RefTests {
@Test
void testRef() {
Ref<String> strRef = new Ref<>("ZhouXY");
assertTrue(strRef.checkValue("ZhouXY"::equals));
apply(strRef);
assertEquals("Hello ZhouXY", strRef.getValue());
log.info("strRef: {}", strRef);
assertTrue(strRef.checkValue(str -> str.length() == 12));
}
void apply(Ref<String> strRef) {
@@ -69,7 +72,7 @@ class RefTests {
}
void apply(boolean condition, CharRef charRef) {
charRef.apply(c -> condition ? '1' : '0');
charRef.transformValue(c -> condition ? '1' : '0');
}
@Test
@@ -81,7 +84,7 @@ class RefTests {
}
void apply(double num, DoubleRef doubleRef) {
doubleRef.apply(d -> d * num);
doubleRef.transformValue(d -> d * num);
}
@Test
@@ -93,7 +96,7 @@ class RefTests {
}
void apply(int num, IntRef intRef) {
intRef.apply(d -> d - num);
intRef.transformValue(d -> d - num);
}
@Test
@@ -105,6 +108,6 @@ class RefTests {
}
void apply(long num, LongRef longRef) {
longRef.apply(d -> d + num);
longRef.transformValue(d -> d + num);
}
}