forked from plusone/plusone-commons
Compare commits
5 Commits
7951172d68
...
86d2716b8d
Author | SHA1 | Date | |
---|---|---|---|
86d2716b8d | |||
3b82e27738 | |||
fb9cb8ada9 | |||
8d24d8de23 | |||
3f0c14f2d9 |
@@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.math;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.errorprone.annotations.Immutable;
|
|
||||||
|
|
||||||
import xyz.zhouxy.plusone.commons.util.Numbers;
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
public class Interval<T extends Comparable<T>> {
|
|
||||||
@Nonnull
|
|
||||||
private final IntervalType intervalType;
|
|
||||||
private final T lowerBound;
|
|
||||||
private final T upperBound;
|
|
||||||
|
|
||||||
public Interval(@Nonnull IntervalType intervalType, T lowerBound, T upperBound) {
|
|
||||||
Preconditions.checkNotNull(intervalType);
|
|
||||||
if (intervalType.isLeftClosed()) {
|
|
||||||
Preconditions.checkArgument(lowerBound != null,
|
|
||||||
"The lower bound cannot be null, when the interval is left-closed.");
|
|
||||||
}
|
|
||||||
if (intervalType.isRightClosed()) {
|
|
||||||
Preconditions.checkArgument(upperBound != null,
|
|
||||||
"The upper bound cannot be null, when the interval is right-closed.");
|
|
||||||
}
|
|
||||||
if (lowerBound != null && upperBound != null) {
|
|
||||||
Preconditions.checkArgument(lowerBound.compareTo(upperBound) <= 0,
|
|
||||||
"The lower bound must less than the upper bound.");
|
|
||||||
}
|
|
||||||
this.intervalType = intervalType;
|
|
||||||
this.lowerBound = lowerBound;
|
|
||||||
this.upperBound = upperBound;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public final IntervalType getIntervalType() {
|
|
||||||
return intervalType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public final Optional<T> getLowerBound() {
|
|
||||||
return Optional.ofNullable(lowerBound);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public final Optional<T> getUpperBound() {
|
|
||||||
return Optional.ofNullable(upperBound);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isLeftClosed() {
|
|
||||||
return this.intervalType.isLeftClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isRightClosed() {
|
|
||||||
return this.intervalType.isRightClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean validValue(@Nonnull T value) {
|
|
||||||
return Numbers.between(value, this.lowerBound, this.upperBound, this.intervalType);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.math;
|
|
||||||
|
|
||||||
public enum IntervalType {
|
|
||||||
/** 开区间。(a,b)={x|a < x < b} */
|
|
||||||
OPEN(false, false),
|
|
||||||
/** 闭区间。[a,b]={x|a ≤ x ≤ b} */
|
|
||||||
CLOSED(true, true),
|
|
||||||
/** 左闭右开区间。[a,b)={x|a ≤ x < b} */
|
|
||||||
CLOSED_OPEN(true, false),
|
|
||||||
/** 左开右闭区间。(a,b]={x|a < x ≤ b} */
|
|
||||||
OPEN_CLOSED(false, true);
|
|
||||||
|
|
||||||
private final boolean leftClosed;
|
|
||||||
private final boolean rightClosed;
|
|
||||||
|
|
||||||
IntervalType(boolean leftClosed, boolean rightClosed) {
|
|
||||||
this.leftClosed = leftClosed;
|
|
||||||
this.rightClosed = rightClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isLeftClosed() {
|
|
||||||
return leftClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isRightClosed() {
|
|
||||||
return rightClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <T extends Comparable<T>> Interval<T> buildInterval(T left, T right) {
|
|
||||||
return new Interval<>(this, left, right);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -18,11 +18,11 @@ package xyz.zhouxy.plusone.commons.time;
|
|||||||
|
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
import java.time.MonthDay;
|
import java.time.MonthDay;
|
||||||
|
import java.time.temporal.ChronoField;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.collect.Range;
|
||||||
|
|
||||||
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
|
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
|
||||||
import xyz.zhouxy.plusone.commons.util.Numbers;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 季度
|
* 季度
|
||||||
@@ -43,11 +43,7 @@ public enum Quarter {
|
|||||||
/** 季度值 (1/2/3/4) */
|
/** 季度值 (1/2/3/4) */
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
/** 季度开始月份 */
|
private final Range<Integer> monthRange;
|
||||||
private final int firstMonth;
|
|
||||||
|
|
||||||
/** 季度结束月份 */
|
|
||||||
private final int lastMonth;
|
|
||||||
|
|
||||||
/** 常量值 */
|
/** 常量值 */
|
||||||
private static final Quarter[] ENUMS = Quarter.values();
|
private static final Quarter[] ENUMS = Quarter.values();
|
||||||
@@ -58,8 +54,10 @@ public enum Quarter {
|
|||||||
Quarter(int value) {
|
Quarter(int value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
||||||
this.lastMonth = value * 3;
|
final int lastMonth = value * 3;
|
||||||
this.firstMonth = this.lastMonth - 2;
|
final int firstMonth = lastMonth - 2;
|
||||||
|
|
||||||
|
this.monthRange = Range.closed(firstMonth, lastMonth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticFactoryMethods
|
// StaticFactoryMethods
|
||||||
@@ -73,7 +71,7 @@ public enum Quarter {
|
|||||||
*/
|
*/
|
||||||
@StaticFactoryMethod(Quarter.class)
|
@StaticFactoryMethod(Quarter.class)
|
||||||
public static Quarter fromMonth(int monthValue) {
|
public static Quarter fromMonth(int monthValue) {
|
||||||
Preconditions.checkArgument(Numbers.between(monthValue, 1, 13), "Invalid value for MonthOfYear: " + monthValue);
|
ChronoField.MONTH_OF_YEAR.checkValidValue(monthValue);
|
||||||
return of(computeQuarterValueInternal(monthValue));
|
return of(computeQuarterValueInternal(monthValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,23 +135,23 @@ public enum Quarter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Month firstMonth() {
|
public Month firstMonth() {
|
||||||
return Month.of(firstMonth);
|
return Month.of(firstMonthValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int firstMonthValue() {
|
public int firstMonthValue() {
|
||||||
return firstMonth;
|
return this.monthRange.lowerEndpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Month lastMonth() {
|
public Month lastMonth() {
|
||||||
return Month.of(lastMonth);
|
return Month.of(lastMonthValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int lastMonthValue() {
|
public int lastMonthValue() {
|
||||||
return lastMonth;
|
return this.monthRange.upperEndpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MonthDay firstMonthDay() {
|
public MonthDay firstMonthDay() {
|
||||||
return MonthDay.of(this.firstMonth, 1);
|
return MonthDay.of(firstMonth(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MonthDay lastMonthDay() {
|
public MonthDay lastMonthDay() {
|
||||||
@@ -163,7 +161,7 @@ public enum Quarter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int firstDayOfYear(boolean leapYear) {
|
public int firstDayOfYear(boolean leapYear) {
|
||||||
return Month.of(this.firstMonth).firstDayOfYear(leapYear);
|
return firstMonth().firstDayOfYear(leapYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters end
|
// Getters end
|
||||||
|
@@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
package xyz.zhouxy.plusone.commons.util;
|
package xyz.zhouxy.plusone.commons.util;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -29,13 +32,17 @@ public class ArrayTools {
|
|||||||
// #region - empty arrays
|
// #region - empty arrays
|
||||||
|
|
||||||
public static final char[] EMPTY_CHAR_ARRAY = {};
|
public static final char[] EMPTY_CHAR_ARRAY = {};
|
||||||
public static final int[] EMPTY_INTEGER_ARRAY = {};
|
public static final byte[] EMPTY_BYTE_ARRAY = {};
|
||||||
|
public static final short[] EMPTY_SHORT_ARRAY = {};
|
||||||
|
public static final int[] EMPTY_INT_ARRAY = {};
|
||||||
public static final long[] EMPTY_LONG_ARRAY = {};
|
public static final long[] EMPTY_LONG_ARRAY = {};
|
||||||
public static final float[] EMPTY_FLOAT_ARRAY = {};
|
public static final float[] EMPTY_FLOAT_ARRAY = {};
|
||||||
public static final double[] EMPTY_DOUBLE_ARRAY = {};
|
public static final double[] EMPTY_DOUBLE_ARRAY = {};
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
public static final int NOT_FOUND_INDEX = -1;
|
||||||
|
|
||||||
// #region - isNullOrEmpty
|
// #region - isNullOrEmpty
|
||||||
|
|
||||||
// isNullOrEmpty
|
// isNullOrEmpty
|
||||||
@@ -51,6 +58,61 @@ public class ArrayTools {
|
|||||||
return arr == null || arr.length == 0;
|
return arr == null || arr.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isNullOrEmpty - char
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNullOrEmpty(@Nullable char[] arr) {
|
||||||
|
return arr == null || arr.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNullOrEmpty - byte
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNullOrEmpty(@Nullable byte[] arr) {
|
||||||
|
return arr == null || arr.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNullOrEmpty - short
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNullOrEmpty(@Nullable short[] arr) {
|
||||||
|
return arr == null || arr.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNullOrEmpty - int
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNullOrEmpty(@Nullable int[] arr) {
|
||||||
|
return arr == null || arr.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNullOrEmpty - long
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNullOrEmpty(@Nullable long[] arr) {
|
||||||
|
return arr == null || arr.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// isNullOrEmpty - float
|
// isNullOrEmpty - float
|
||||||
/**
|
/**
|
||||||
* 检查给定数组是否为空
|
* 检查给定数组是否为空
|
||||||
@@ -73,39 +135,6 @@ public class ArrayTools {
|
|||||||
return arr == null || arr.length == 0;
|
return arr == null || arr.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// isNullOrEmpty - byte
|
|
||||||
/**
|
|
||||||
* 检查给定数组是否为空
|
|
||||||
*
|
|
||||||
* @param arr 待检查的数组,可以为 {@code null}
|
|
||||||
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
|
||||||
*/
|
|
||||||
public static boolean isNullOrEmpty(@Nullable byte[] arr) {
|
|
||||||
return arr == null || arr.length == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNullOrEmpty - long
|
|
||||||
/**
|
|
||||||
* 检查给定数组是否为空
|
|
||||||
*
|
|
||||||
* @param arr 待检查的数组,可以为 {@code null}
|
|
||||||
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
|
||||||
*/
|
|
||||||
public static boolean isNullOrEmpty(@Nullable long[] arr) {
|
|
||||||
return arr == null || arr.length == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNullOrEmpty - int
|
|
||||||
/**
|
|
||||||
* 检查给定数组是否为空
|
|
||||||
*
|
|
||||||
* @param arr 待检查的数组,可以为 {@code null}
|
|
||||||
* @return 如果数组为 {@code null} 或长度为 0,则返回 {@code true};否则返回 {@code false}
|
|
||||||
*/
|
|
||||||
public static boolean isNullOrEmpty(@Nullable int[] arr) {
|
|
||||||
return arr == null || arr.length == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region - isNotEmpty
|
// #region - isNotEmpty
|
||||||
@@ -122,6 +151,61 @@ public class ArrayTools {
|
|||||||
return arr != null && arr.length > 0;
|
return arr != null && arr.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isNotEmpty - char
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否不为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNotEmpty(@Nullable char[] arr) {
|
||||||
|
return arr != null && arr.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNotEmpty - byte
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否不为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNotEmpty(@Nullable byte[] arr) {
|
||||||
|
return arr != null && arr.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNotEmpty - short
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否不为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNotEmpty(@Nullable short[] arr) {
|
||||||
|
return arr != null && arr.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNotEmpty - int
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否不为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNotEmpty(@Nullable int[] arr) {
|
||||||
|
return arr != null && arr.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNotEmpty - long
|
||||||
|
/**
|
||||||
|
* 检查给定数组是否不为空
|
||||||
|
*
|
||||||
|
* @param arr 待检查的数组,可以为 {@code null}
|
||||||
|
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
public static boolean isNotEmpty(@Nullable long[] arr) {
|
||||||
|
return arr != null && arr.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
// isNotEmpty - float
|
// isNotEmpty - float
|
||||||
/**
|
/**
|
||||||
* 检查给定数组是否不为空
|
* 检查给定数组是否不为空
|
||||||
@@ -144,39 +228,6 @@ public class ArrayTools {
|
|||||||
return arr != null && arr.length > 0;
|
return arr != null && arr.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// isNotEmpty - byte
|
|
||||||
/**
|
|
||||||
* 检查给定数组是否不为空
|
|
||||||
*
|
|
||||||
* @param arr 待检查的数组,可以为 {@code null}
|
|
||||||
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
|
||||||
*/
|
|
||||||
public static boolean isNotEmpty(@Nullable byte[] arr) {
|
|
||||||
return arr != null && arr.length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNotEmpty - long
|
|
||||||
/**
|
|
||||||
* 检查给定数组是否不为空
|
|
||||||
*
|
|
||||||
* @param arr 待检查的数组,可以为 {@code null}
|
|
||||||
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
|
||||||
*/
|
|
||||||
public static boolean isNotEmpty(@Nullable long[] arr) {
|
|
||||||
return arr != null && arr.length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNotEmpty - int
|
|
||||||
/**
|
|
||||||
* 检查给定数组是否不为空
|
|
||||||
*
|
|
||||||
* @param arr 待检查的数组,可以为 {@code null}
|
|
||||||
* @return 如果数组不为 {@code null} 且长度大于 0,则返回 {@code true};否则返回 {@code false}
|
|
||||||
*/
|
|
||||||
public static boolean isNotEmpty(@Nullable int[] arr) {
|
|
||||||
return arr != null && arr.length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region - isAllElementsNotNull
|
// #region - isAllElementsNotNull
|
||||||
@@ -216,34 +267,14 @@ public class ArrayTools {
|
|||||||
* @param arrays 数组集合,可以为 {@code null}
|
* @param arrays 数组集合,可以为 {@code null}
|
||||||
* @return 拼接后的数组
|
* @return 拼接后的数组
|
||||||
*/
|
*/
|
||||||
public static float[] concatFloatArray(@Nullable Collection<float[]> arrays) {
|
public static char[] concatCharArray(@Nullable Collection<char[]> arrays) {
|
||||||
if (arrays == null || arrays.isEmpty()) {
|
if (arrays == null || arrays.isEmpty()) {
|
||||||
return new float[0];
|
return new char[0];
|
||||||
}
|
}
|
||||||
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
||||||
final float[] result = new float[length];
|
final char[] result = new char[length];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (float[] arr : arrays) {
|
for (char[] arr : arrays) {
|
||||||
System.arraycopy(arr, 0, result, i, arr.length);
|
|
||||||
i += arr.length;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拼接多个数组
|
|
||||||
*
|
|
||||||
* @param arrays 数组集合,可以为 {@code null}
|
|
||||||
* @return 拼接后的数组
|
|
||||||
*/
|
|
||||||
public static double[] concatDoubleArray(@Nullable Collection<double[]> arrays) {
|
|
||||||
if (arrays == null || arrays.isEmpty()) {
|
|
||||||
return new double[0];
|
|
||||||
}
|
|
||||||
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
|
||||||
final double[] result = new double[length];
|
|
||||||
int i = 0;
|
|
||||||
for (double[] arr : arrays) {
|
|
||||||
System.arraycopy(arr, 0, result, i, arr.length);
|
System.arraycopy(arr, 0, result, i, arr.length);
|
||||||
i += arr.length;
|
i += arr.length;
|
||||||
}
|
}
|
||||||
@@ -276,14 +307,14 @@ public class ArrayTools {
|
|||||||
* @param arrays 数组集合,可以为 {@code null}
|
* @param arrays 数组集合,可以为 {@code null}
|
||||||
* @return 拼接后的数组
|
* @return 拼接后的数组
|
||||||
*/
|
*/
|
||||||
public static long[] concatLongArray(@Nullable Collection<long[]> arrays) {
|
public static short[] concatShortArray(@Nullable Collection<short[]> arrays) {
|
||||||
if (arrays == null || arrays.isEmpty()) {
|
if (arrays == null || arrays.isEmpty()) {
|
||||||
return new long[0];
|
return new short[0];
|
||||||
}
|
}
|
||||||
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
||||||
final long[] result = new long[length];
|
final short[] result = new short[length];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (long[] arr : arrays) {
|
for (short[] arr : arrays) {
|
||||||
System.arraycopy(arr, 0, result, i, arr.length);
|
System.arraycopy(arr, 0, result, i, arr.length);
|
||||||
i += arr.length;
|
i += arr.length;
|
||||||
}
|
}
|
||||||
@@ -310,6 +341,66 @@ public class ArrayTools {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼接多个数组
|
||||||
|
*
|
||||||
|
* @param arrays 数组集合,可以为 {@code null}
|
||||||
|
* @return 拼接后的数组
|
||||||
|
*/
|
||||||
|
public static long[] concatLongArray(@Nullable Collection<long[]> arrays) {
|
||||||
|
if (arrays == null || arrays.isEmpty()) {
|
||||||
|
return new long[0];
|
||||||
|
}
|
||||||
|
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
||||||
|
final long[] result = new long[length];
|
||||||
|
int i = 0;
|
||||||
|
for (long[] arr : arrays) {
|
||||||
|
System.arraycopy(arr, 0, result, i, arr.length);
|
||||||
|
i += arr.length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼接多个数组
|
||||||
|
*
|
||||||
|
* @param arrays 数组集合,可以为 {@code null}
|
||||||
|
* @return 拼接后的数组
|
||||||
|
*/
|
||||||
|
public static float[] concatFloatArray(@Nullable Collection<float[]> arrays) {
|
||||||
|
if (arrays == null || arrays.isEmpty()) {
|
||||||
|
return new float[0];
|
||||||
|
}
|
||||||
|
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
||||||
|
final float[] result = new float[length];
|
||||||
|
int i = 0;
|
||||||
|
for (float[] arr : arrays) {
|
||||||
|
System.arraycopy(arr, 0, result, i, arr.length);
|
||||||
|
i += arr.length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼接多个数组
|
||||||
|
*
|
||||||
|
* @param arrays 数组集合,可以为 {@code null}
|
||||||
|
* @return 拼接后的数组
|
||||||
|
*/
|
||||||
|
public static double[] concatDoubleArray(@Nullable Collection<double[]> arrays) {
|
||||||
|
if (arrays == null || arrays.isEmpty()) {
|
||||||
|
return new double[0];
|
||||||
|
}
|
||||||
|
final int length = arrays.stream().mapToInt(a -> a.length).sum();
|
||||||
|
final double[] result = new double[length];
|
||||||
|
int i = 0;
|
||||||
|
for (double[] arr : arrays) {
|
||||||
|
System.arraycopy(arr, 0, result, i, arr.length);
|
||||||
|
i += arr.length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将集合中的数组连接为一个列表
|
* 将集合中的数组连接为一个列表
|
||||||
*
|
*
|
||||||
@@ -360,6 +451,69 @@ public class ArrayTools {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// repeat - byte
|
||||||
|
|
||||||
|
public static byte[] repeat(byte[] arr, int times) {
|
||||||
|
return repeat(arr, times, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] repeat(byte[] arr, int times, int maxLength) {
|
||||||
|
AssertTools.checkArgumentNotNull(arr);
|
||||||
|
AssertTools.checkArgument(times >= 0,
|
||||||
|
"The number of times must be greater than or equal to zero");
|
||||||
|
AssertTools.checkArgument(maxLength >= 0,
|
||||||
|
"The max length must be greater than or equal to zero");
|
||||||
|
if (times == 0) {
|
||||||
|
return EMPTY_BYTE_ARRAY;
|
||||||
|
}
|
||||||
|
final int length = Integer.min(arr.length * times, maxLength);
|
||||||
|
final byte[] result = new byte[length];
|
||||||
|
fill(result, 0, length, arr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeat - short
|
||||||
|
|
||||||
|
public static short[] repeat(short[] arr, int times) {
|
||||||
|
return repeat(arr, times, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short[] repeat(short[] arr, int times, int maxLength) {
|
||||||
|
AssertTools.checkArgumentNotNull(arr);
|
||||||
|
AssertTools.checkArgument(times >= 0,
|
||||||
|
"The number of times must be greater than or equal to zero");
|
||||||
|
AssertTools.checkArgument(maxLength >= 0,
|
||||||
|
"The max length must be greater than or equal to zero");
|
||||||
|
if (times == 0) {
|
||||||
|
return EMPTY_SHORT_ARRAY;
|
||||||
|
}
|
||||||
|
final int length = Integer.min(arr.length * times, maxLength);
|
||||||
|
final short[] result = new short[length];
|
||||||
|
fill(result, 0, length, arr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeat - int
|
||||||
|
|
||||||
|
public static int[] repeat(int[] arr, int times) {
|
||||||
|
return repeat(arr, times, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] repeat(int[] arr, int times, int maxLength) {
|
||||||
|
AssertTools.checkArgumentNotNull(arr);
|
||||||
|
AssertTools.checkArgument(times >= 0,
|
||||||
|
"The number of times must be greater than or equal to zero");
|
||||||
|
AssertTools.checkArgument(maxLength >= 0,
|
||||||
|
"The max length must be greater than or equal to zero");
|
||||||
|
if (times == 0) {
|
||||||
|
return EMPTY_INT_ARRAY;
|
||||||
|
}
|
||||||
|
final int length = Integer.min(arr.length * times, maxLength);
|
||||||
|
final int[] result = new int[length];
|
||||||
|
fill(result, 0, length, arr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// repeat - long
|
// repeat - long
|
||||||
|
|
||||||
public static long[] repeat(long[] arr, int times) {
|
public static long[] repeat(long[] arr, int times) {
|
||||||
@@ -460,6 +614,93 @@ public class ArrayTools {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill - byte
|
||||||
|
|
||||||
|
public static void fill(byte[] a, byte... values) {
|
||||||
|
fill(a, 0, a.length, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fill(byte[] a, int fromIndex, int toIndex, byte... values) {
|
||||||
|
AssertTools.checkArgumentNotNull(a);
|
||||||
|
if (values.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int start = Integer.max(fromIndex, 0);
|
||||||
|
final int end = Integer.min(toIndex, a.length);
|
||||||
|
if (start >= end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = start; i < end; i += values.length) {
|
||||||
|
for (int j = 0; j < values.length; j++) {
|
||||||
|
final int k = (i + j);
|
||||||
|
if (k < end) {
|
||||||
|
a[k] = values[j];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill - short
|
||||||
|
|
||||||
|
public static void fill(short[] a, short... values) {
|
||||||
|
fill(a, 0, a.length, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fill(short[] a, int fromIndex, int toIndex, short... values) {
|
||||||
|
AssertTools.checkArgumentNotNull(a);
|
||||||
|
if (values.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int start = Integer.max(fromIndex, 0);
|
||||||
|
final int end = Integer.min(toIndex, a.length);
|
||||||
|
if (start >= end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = start; i < end; i += values.length) {
|
||||||
|
for (int j = 0; j < values.length; j++) {
|
||||||
|
final int k = (i + j);
|
||||||
|
if (k < end) {
|
||||||
|
a[k] = values[j];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill - int
|
||||||
|
|
||||||
|
public static void fill(int[] a, int... values) {
|
||||||
|
fill(a, 0, a.length, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fill(int[] a, int fromIndex, int toIndex, int... values) {
|
||||||
|
AssertTools.checkArgumentNotNull(a);
|
||||||
|
if (values.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int start = Integer.max(fromIndex, 0);
|
||||||
|
final int end = Integer.min(toIndex, a.length);
|
||||||
|
if (start >= end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = start; i < end; i += values.length) {
|
||||||
|
for (int j = 0; j < values.length; j++) {
|
||||||
|
final int k = (i + j);
|
||||||
|
if (k < end) {
|
||||||
|
a[k] = values[j];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fill - long
|
// fill - long
|
||||||
|
|
||||||
public static void fill(long[] a, long... values) {
|
public static void fill(long[] a, long... values) {
|
||||||
@@ -582,6 +823,256 @@ public class ArrayTools {
|
|||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
// #region - indexOf
|
||||||
|
|
||||||
|
public static <T> int indexOf(T[] arr, Predicate<? super T> predicate) { // TODO 单元测试
|
||||||
|
AssertTools.checkNotNull(predicate);
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (predicate.test(arr[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int indexOf(T[] arr, T obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, item -> Objects.equals(item, obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int indexOf(char[] arr, char value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == value) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int indexOf(byte[] arr, byte value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == value) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int indexOf(short[] arr, short value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == value) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int indexOf(int[] arr, int value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == value) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int indexOf(long[] arr, long value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == value) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int indexOf(float[] arr, float value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == value) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int indexOf(double[] arr, double value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == value) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region - lastIndexOf
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(T[] arr, @Nonnull Predicate<? super T> predicate) { // TODO 单元测试
|
||||||
|
AssertTools.checkNotNull(predicate);
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (predicate.test(arr[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(T[] arr, T obj) { // TODO 单元测试
|
||||||
|
return lastIndexOf(arr, item -> Objects.equals(item, obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(char[] arr, char value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (value == arr[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(byte[] arr, byte value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (value == arr[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(short[] arr, short value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (value == arr[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(int[] arr, int value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (value == arr[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(long[] arr, long value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (value == arr[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(float[] arr, float value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (value == arr[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> int lastIndexOf(double[] arr, double value) { // TODO 单元测试
|
||||||
|
if (isNullOrEmpty(arr)) {
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
for (int i = arr.length - 1; i >= 0; i--) {
|
||||||
|
if (value == arr[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region - contains
|
||||||
|
|
||||||
|
public static <T> boolean contains(T[] arr, T obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(char[] arr, char obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(byte[] arr, byte obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(short[] arr, short obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(int[] arr, int obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(long[] arr, long obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(float[] arr, float obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(double[] arr, double obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, obj) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean containsValue(BigDecimal[] arr, BigDecimal obj) { // TODO 单元测试
|
||||||
|
return indexOf(arr, item -> BigDecimals.equalsValue(item, obj)) > NOT_FOUND_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
// #region - private constructor
|
// #region - private constructor
|
||||||
|
|
||||||
private ArrayTools() {
|
private ArrayTools() {
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
package xyz.zhouxy.plusone.commons.util;
|
package xyz.zhouxy.plusone.commons.util;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
@@ -49,6 +51,25 @@ public class BigDecimals {
|
|||||||
return lt(a, b) || equalsValue(a, b);
|
return lt(a, b) || equalsValue(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BigDecimal sum(final BigDecimal... numbers) {
|
||||||
|
if (ArrayTools.isNullOrEmpty(numbers)) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
BigDecimal result = BigDecimals.nullToZero(numbers[0]);
|
||||||
|
for (int i = 1; i < numbers.length; i++) {
|
||||||
|
BigDecimal value = numbers[i];
|
||||||
|
if (value != null) {
|
||||||
|
result = result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public static BigDecimal nullToZero(@Nullable final BigDecimal val) {
|
||||||
|
return val != null ? val : BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
@StaticFactoryMethod(BigDecimal.class)
|
@StaticFactoryMethod(BigDecimal.class)
|
||||||
public static BigDecimal of(final String val) {
|
public static BigDecimal of(final String val) {
|
||||||
return (StringTools.isNotBlank(val)) ? new BigDecimal(val) : BigDecimal.ZERO;
|
return (StringTools.isNotBlank(val)) ? new BigDecimal(val) : BigDecimal.ZERO;
|
||||||
|
@@ -67,6 +67,8 @@ public class DateTimeTools {
|
|||||||
return DATE_TIME_FORMATTER_CACHE.getUnchecked(pattern);
|
return DATE_TIME_FORMATTER_CACHE.getUnchecked(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #region - toString
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将日期时间转换为指定格式的字符串
|
* 将日期时间转换为指定格式的字符串
|
||||||
*
|
*
|
||||||
@@ -103,6 +105,10 @@ public class DateTimeTools {
|
|||||||
return toString(pattern, dateTime);
|
return toString(pattern, dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region - nowStr
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定格式,返回当前时间戳对应的字符串
|
* 指定格式,返回当前时间戳对应的字符串
|
||||||
*
|
*
|
||||||
@@ -124,7 +130,9 @@ public class DateTimeTools {
|
|||||||
return toString(pattern, Instant.now().atZone(zone));
|
return toString(pattern, Instant.now().atZone(zone));
|
||||||
}
|
}
|
||||||
|
|
||||||
// toDate
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toDate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将时间戳转换为 {@link Date} 对象
|
* 将时间戳转换为 {@link Date} 对象
|
||||||
@@ -189,7 +197,9 @@ public class DateTimeTools {
|
|||||||
return Date.from(ZonedDateTime.of(localDate, localTime, zone).toInstant());
|
return Date.from(ZonedDateTime.of(localDate, localTime, zone).toInstant());
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInstant
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toInstant
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将时间戳转换为 {@link Instant} 对象
|
* 将时间戳转换为 {@link Instant} 对象
|
||||||
@@ -244,7 +254,9 @@ public class DateTimeTools {
|
|||||||
return ZonedDateTime.of(localDateTime, zone).toInstant();
|
return ZonedDateTime.of(localDateTime, zone).toInstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
// toZonedDateTime
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toZonedDateTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取时间戳在指定时区的地区时间。
|
* 获取时间戳在指定时区的地区时间。
|
||||||
@@ -338,7 +350,9 @@ public class DateTimeTools {
|
|||||||
return ZonedDateTime.of(localDateTime, zone);
|
return ZonedDateTime.of(localDateTime, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
// toLocalDateTime
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toLocalDateTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取时间戳在指定时区的地区时间。
|
* 获取时间戳在指定时区的地区时间。
|
||||||
@@ -406,9 +420,11 @@ public class DateTimeTools {
|
|||||||
return LocalDateTime.ofInstant(zonedDateTime.toInstant(), zone);
|
return LocalDateTime.ofInstant(zonedDateTime.toInstant(), zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
|
|
||||||
// toJodaInstant
|
// #region - toJodaInstant
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 {@link java.time.Instant} 转换为 {@link org.joda.time.Instant}
|
* 将 {@link java.time.Instant} 转换为 {@link org.joda.time.Instant}
|
||||||
@@ -441,7 +457,9 @@ public class DateTimeTools {
|
|||||||
return toJodaInstant(java.time.ZonedDateTime.of(localDateTime, zone));
|
return toJodaInstant(java.time.ZonedDateTime.of(localDateTime, zone));
|
||||||
}
|
}
|
||||||
|
|
||||||
// toJavaInstant
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toJavaInstant
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 {@link org.joda.time.Instant} 对象转换为 {@link java.time.Instant} 对象
|
* 将 {@link org.joda.time.Instant} 对象转换为 {@link java.time.Instant} 对象
|
||||||
@@ -479,7 +497,9 @@ public class DateTimeTools {
|
|||||||
return toJavaInstant(localDateTime.toDateTime(zone));
|
return toJavaInstant(localDateTime.toDateTime(zone));
|
||||||
}
|
}
|
||||||
|
|
||||||
// toJodaDateTime
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toJodaDateTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 Java 中表示日期时间的 {@link java.time.ZonedDateTime} 对象
|
* 将 Java 中表示日期时间的 {@link java.time.ZonedDateTime} 对象
|
||||||
@@ -506,7 +526,7 @@ public class DateTimeTools {
|
|||||||
public static org.joda.time.DateTime toJodaDateTime(
|
public static org.joda.time.DateTime toJodaDateTime(
|
||||||
java.time.LocalDateTime localDateTime,
|
java.time.LocalDateTime localDateTime,
|
||||||
java.time.ZoneId zone) {
|
java.time.ZoneId zone) {
|
||||||
org.joda.time.DateTimeZone dateTimeZone = toJodaTime(zone);
|
org.joda.time.DateTimeZone dateTimeZone = toJodaZone(zone);
|
||||||
return toJodaInstant(ZonedDateTime.of(localDateTime, zone).toInstant()).toDateTime(dateTimeZone);
|
return toJodaInstant(ZonedDateTime.of(localDateTime, zone).toInstant()).toDateTime(dateTimeZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,11 +540,13 @@ public class DateTimeTools {
|
|||||||
public static org.joda.time.DateTime toJodaDateTime(
|
public static org.joda.time.DateTime toJodaDateTime(
|
||||||
java.time.Instant instant,
|
java.time.Instant instant,
|
||||||
java.time.ZoneId zone) {
|
java.time.ZoneId zone) {
|
||||||
org.joda.time.DateTimeZone dateTimeZone = toJodaTime(zone);
|
org.joda.time.DateTimeZone dateTimeZone = toJodaZone(zone);
|
||||||
return toJodaInstant(instant).toDateTime(dateTimeZone);
|
return toJodaInstant(instant).toDateTime(dateTimeZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
// toZonedDateTime
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toZonedDateTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 joda-time 中带时区的日期时间,转换为 java.time 中带时区的日期时间
|
* 将 joda-time 中带时区的日期时间,转换为 java.time 中带时区的日期时间
|
||||||
@@ -568,7 +590,9 @@ public class DateTimeTools {
|
|||||||
return toJavaInstant(instant).atZone(zone);
|
return toJavaInstant(instant).atZone(zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
// toJodaLocalDateTime
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toJodaLocalDateTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 {@link java.time.LocalDateTime} 转换为 {@link org.joda.time.LocalDateTime}
|
* 将 {@link java.time.LocalDateTime} 转换为 {@link org.joda.time.LocalDateTime}
|
||||||
@@ -578,11 +602,13 @@ public class DateTimeTools {
|
|||||||
*/
|
*/
|
||||||
public static org.joda.time.LocalDateTime toJodaLocalDateTime(java.time.LocalDateTime localDateTime) {
|
public static org.joda.time.LocalDateTime toJodaLocalDateTime(java.time.LocalDateTime localDateTime) {
|
||||||
java.time.ZoneId javaZone = java.time.ZoneId.systemDefault();
|
java.time.ZoneId javaZone = java.time.ZoneId.systemDefault();
|
||||||
org.joda.time.DateTimeZone jodaZone = toJodaTime(javaZone);
|
org.joda.time.DateTimeZone jodaZone = toJodaZone(javaZone);
|
||||||
return toJodaInstant(localDateTime, javaZone).toDateTime(jodaZone).toLocalDateTime();
|
return toJodaInstant(localDateTime, javaZone).toDateTime(jodaZone).toLocalDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
// toJavaLocalDateTime
|
// #endregion
|
||||||
|
|
||||||
|
// #region - toJavaLocalDateTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 {@link org.joda.time.LocalDateTime} 转换为 {@link java.time.LocalDateTime}
|
* 将 {@link org.joda.time.LocalDateTime} 转换为 {@link java.time.LocalDateTime}
|
||||||
@@ -596,6 +622,10 @@ public class DateTimeTools {
|
|||||||
return toJavaInstant(localDateTime, jodaZone).atZone(javaZone).toLocalDateTime();
|
return toJavaInstant(localDateTime, jodaZone).atZone(javaZone).toLocalDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region - ZoneId <--> DateTimeZone
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换 Java API 和 joda-time API 表示时区的对象
|
* 转换 Java API 和 joda-time API 表示时区的对象
|
||||||
*
|
*
|
||||||
@@ -612,11 +642,13 @@ public class DateTimeTools {
|
|||||||
* @param zone Java API 中表示时区的对象
|
* @param zone Java API 中表示时区的对象
|
||||||
* @return joda-time API 中表示时区的对象
|
* @return joda-time API 中表示时区的对象
|
||||||
*/
|
*/
|
||||||
public static org.joda.time.DateTimeZone toJodaTime(java.time.ZoneId zone) {
|
public static org.joda.time.DateTimeZone toJodaZone(java.time.ZoneId zone) {
|
||||||
return org.joda.time.DateTimeZone.forID(zone.getId());
|
return org.joda.time.DateTimeZone.forID(zone.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// getQuarter
|
// #endregion
|
||||||
|
|
||||||
|
// #region - YearQuarter & Quarter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定日期所在季度
|
* 获取指定日期所在季度
|
||||||
@@ -679,6 +711,8 @@ public class DateTimeTools {
|
|||||||
return YearQuarter.of(date);
|
return YearQuarter.of(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 私有构造方法,明确标识该常量类的作用。
|
* 私有构造方法,明确标识该常量类的作用。
|
||||||
*/
|
*/
|
||||||
|
@@ -17,12 +17,10 @@
|
|||||||
package xyz.zhouxy.plusone.commons.util;
|
package xyz.zhouxy.plusone.commons.util;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
|
|
||||||
import xyz.zhouxy.plusone.commons.math.IntervalType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Numbers
|
* Numbers
|
||||||
@@ -31,7 +29,7 @@ import xyz.zhouxy.plusone.commons.math.IntervalType;
|
|||||||
*/
|
*/
|
||||||
public class Numbers {
|
public class Numbers {
|
||||||
|
|
||||||
// sum
|
// #region - sum
|
||||||
|
|
||||||
public static int sum(final short... numbers) {
|
public static int sum(final short... numbers) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@@ -73,105 +71,60 @@ public class Numbers {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BigDecimal sum(final BigDecimal... numbers) {
|
public static BigInteger sum(final BigInteger... numbers) {
|
||||||
BigDecimal result = BigDecimals.of("0.00");
|
if (ArrayTools.isNullOrEmpty(numbers)) {
|
||||||
for (BigDecimal number : numbers) {
|
return BigInteger.ZERO;
|
||||||
result = result.add(number);
|
}
|
||||||
|
BigInteger result = Numbers.nullToZero(numbers[0]);
|
||||||
|
for (int i = 1; i < numbers.length; i++) {
|
||||||
|
BigInteger value = numbers[i];
|
||||||
|
if (value != null) {
|
||||||
|
result = result.add(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// between
|
public static BigDecimal sum(final BigDecimal... numbers) {
|
||||||
|
return BigDecimals.sum(numbers);
|
||||||
public static boolean between(int value, int min, int max) {
|
|
||||||
return between(value, min, max, IntervalType.CLOSED_OPEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean between(int value, int min, int max, IntervalType intervalType) {
|
// #endregion
|
||||||
final IntervalType intervalTypeToUse = intervalType != null
|
|
||||||
? intervalType
|
// #region - nullToZero
|
||||||
: IntervalType.CLOSED_OPEN;
|
|
||||||
switch (intervalTypeToUse) {
|
public static short nullToZero(@Nullable final Short val) {
|
||||||
case OPEN:
|
return val != null ? val : 0;
|
||||||
return min < value && value < max;
|
|
||||||
case CLOSED:
|
|
||||||
return min <= value && value <= max;
|
|
||||||
case OPEN_CLOSED:
|
|
||||||
return min < value && value <= max;
|
|
||||||
case CLOSED_OPEN:
|
|
||||||
default:
|
|
||||||
return min <= value && value < max;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean between(long value, long min, long max) {
|
public static int nullToZero(@Nullable final Integer val) {
|
||||||
return between(value, min, max, IntervalType.CLOSED_OPEN);
|
return val != null ? val : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean between(long value, long min, long max, IntervalType intervalType) {
|
public static long nullToZero(@Nullable final Long val) {
|
||||||
final IntervalType intervalTypeToUse = intervalType != null
|
return val != null ? val : 0L;
|
||||||
? intervalType
|
|
||||||
: IntervalType.CLOSED_OPEN;
|
|
||||||
switch (intervalTypeToUse) {
|
|
||||||
case OPEN:
|
|
||||||
return min < value && value < max;
|
|
||||||
case CLOSED:
|
|
||||||
return min <= value && value <= max;
|
|
||||||
case OPEN_CLOSED:
|
|
||||||
return min < value && value <= max;
|
|
||||||
case CLOSED_OPEN:
|
|
||||||
default:
|
|
||||||
return min <= value && value < max;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean between(double value, double min, double max) {
|
public static float nullToZero(@Nullable final Float val) {
|
||||||
return between(value, min, max, IntervalType.CLOSED_OPEN);
|
return val != null ? val : 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean between(double value, double min, double max, IntervalType intervalType) {
|
public static double nullToZero(@Nullable final Double val) {
|
||||||
final IntervalType intervalTypeToUse = intervalType != null
|
return val != null ? val : 0.0;
|
||||||
? intervalType
|
|
||||||
: IntervalType.CLOSED_OPEN;
|
|
||||||
switch (intervalTypeToUse) {
|
|
||||||
case OPEN:
|
|
||||||
return min < value && value < max;
|
|
||||||
case CLOSED:
|
|
||||||
return min <= value && value <= max;
|
|
||||||
case OPEN_CLOSED:
|
|
||||||
return min < value && value <= max;
|
|
||||||
case CLOSED_OPEN:
|
|
||||||
default:
|
|
||||||
return min <= value && value < max;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Comparable<T>> boolean between(@Nonnull T value, T min, T max) {
|
@Nonnull
|
||||||
return between(value, min, max, IntervalType.CLOSED_OPEN);
|
public static BigInteger nullToZero(@Nullable final BigInteger val) {
|
||||||
|
return val != null ? val : BigInteger.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Comparable<T>> boolean between(@Nonnull T value, T min, T max, IntervalType intervalType) {
|
@Nonnull
|
||||||
Preconditions.checkArgument(value != null, "The value to valid connot be null.");
|
public static BigDecimal nullToZero(@Nullable final BigDecimal val) {
|
||||||
IntervalType intervalTypeToUse = intervalType != null
|
return BigDecimals.nullToZero(val);
|
||||||
? intervalType
|
|
||||||
: IntervalType.CLOSED_OPEN;
|
|
||||||
switch (intervalTypeToUse) {
|
|
||||||
case OPEN:
|
|
||||||
return (min == null || min.compareTo(value) < 0)
|
|
||||||
&& (max == null || value.compareTo(max) < 0);
|
|
||||||
case CLOSED:
|
|
||||||
return (min == null || min.compareTo(value) <= 0)
|
|
||||||
&& (max == null || value.compareTo(max) <= 0);
|
|
||||||
case OPEN_CLOSED:
|
|
||||||
return (min == null || min.compareTo(value) < 0)
|
|
||||||
&& (max == null || value.compareTo(max) <= 0);
|
|
||||||
case CLOSED_OPEN:
|
|
||||||
default:
|
|
||||||
return (min == null || min.compareTo(value) <= 0)
|
|
||||||
&& (max == null || value.compareTo(max) < 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
private Numbers() {
|
private Numbers() {
|
||||||
throw new IllegalStateException("Utility class");
|
throw new IllegalStateException("Utility class");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user