This commit is contained in:
Looly
2022-10-08 20:51:45 +08:00
parent 45c87bd1ff
commit fd138c2b70
6 changed files with 135 additions and 129 deletions

View File

@@ -352,4 +352,98 @@ public class CompareUtil {
public static <T extends Comparable<? super T>> T max(final T t1, final T t2) {
return compare(t1, t2) >= 0 ? t1 : t2;
}
/**
* {@code null}安全的检查两个对象是否相同,通过调用{@code compare(c1, c2) == 0}完成
*
* @param <T> 被比较对象类型
* @param c1 对象1可以为{@code null}
* @param c2 对象2可以为{@code null}
* @return 是否相等
* @see java.util.Comparator#compare(Object, Object)
*/
public static <T extends Comparable<? super T>> boolean equals(final T c1, final T c2) {
return compare(c1, c2) == 0;
}
/**
* c1是否大于c2通过调用{@code compare(c1, c2) > 0}完成
*
* @param <T> 被比较对象类型
* @param c1 对象1可以为{@code null}
* @param c2 对象2可以为{@code null}
* @return c1是否大于c2
* @see java.util.Comparator#compare(Object, Object)
*/
public static <T extends Comparable<? super T>> boolean gt(final T c1, final T c2) {
return compare(c1, c2) > 0;
}
/**
* c1是否大于或等于c2通过调用{@code compare(c1, c2) >= 0}完成
*
* @param <T> 被比较对象类型
* @param c1 对象1可以为{@code null}
* @param c2 对象2可以为{@code null}
* @return c1是否大于或等于c2
* @see java.util.Comparator#compare(Object, Object)
*/
public static <T extends Comparable<? super T>> boolean ge(final T c1, final T c2) {
return compare(c1, c2) >= 0;
}
/**
* c1是否大小于c2通过调用{@code compare(c1, c2) < 0}完成
*
* @param <T> 被比较对象类型
* @param c1 对象1可以为{@code null}
* @param c2 对象2可以为{@code null}
* @return c1是否小于c2
* @see java.util.Comparator#compare(Object, Object)
*/
public static <T extends Comparable<? super T>> boolean lt(final T c1, final T c2) {
return compare(c1, c2) < 0;
}
/**
* c1是否小于或等于c2通过调用{@code compare(c1, c2) <= 0}完成
*
* @param <T> 被比较对象类型
* @param c1 对象1可以为{@code null}
* @param c2 对象2可以为{@code null}
* @return c1是否小于或等于c2
* @see java.util.Comparator#compare(Object, Object)
*/
public static <T extends Comparable<? super T>> boolean le(final T c1, final T c2) {
return compare(c1, c2) <= 0;
}
/**
* 给定的{@code value}是否在{@code c1}和{@code c2}的范围内<br>
* 即 {@code min(c1,c2) <= value <= max(c1,c2)}
*
* @param <T> 被比较对象类型
* @param value 检查的对象,可以为{@code null}
* @param c1 对象1可以为{@code null}
* @param c2 对象2可以为{@code null}
* @return 给定的{@code value}是否在{@code c1}和{@code c2}的范围内
*/
public static <T extends Comparable<? super T>> boolean isIn(final T value, final T c1, final T c2) {
return ge(value, min(c1, c2)) && le(value, max(c1, c2));
}
/**
* 给定的{@code value}是否在{@code c1}和{@code c2}的范围内,但是不包括边界<br>
* 即 {@code min(c1,c2) < value < max(c1,c2)}
*
* @param <T> 被比较对象类型
* @param value 检查的对象,可以为{@code null}
* @param c1 对象1可以为{@code null}
* @param c2 对象2可以为{@code null}
* @return c1是否小于或等于c2
* @see java.util.Comparator#compare(Object, Object)
*/
public static <T extends Comparable<? super T>> boolean isInExclusive(final T value, final T c1, final T c2) {
return gt(value, min(c1, c2)) && lt(value, max(c1, c2));
}
}

View File

@@ -299,7 +299,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
// 上界小于下界时为空
return compareValue > 0
// 上下界的边界值相等,且不为退化区间是为空
|| !(low.getType().isClose() && up.getType().isClose());
|| false == (low.getType().isClose() && up.getType().isClose());
}
/**
@@ -347,7 +347,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
/**
* {@code other}是否是当前区间的子集
*
* @param other 另一区间
* @param other 另一区间
* @return 是否
*/
public boolean isSuperset(final BoundedRange<T> other) {
@@ -358,7 +358,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
/**
* {@code other}是否是当前区间的子集
*
* @param other 另一区间
* @param other 另一区间
* @return 是否
*/
public boolean isProperSuperset(final BoundedRange<T> other) {
@@ -369,7 +369,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
/**
* 当前区间是否是{@code other}的子集
*
* @param other 另一区间
* @param other 另一区间
* @return 是否
*/
public boolean isSubset(final BoundedRange<T> other) {
@@ -380,7 +380,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
/**
* 当前区间是否是{@code other}的真子集
*
* @param other 另一区间
* @param other 另一区间
* @return 是否
*/
public boolean isProperSubset(final BoundedRange<T> other) {
@@ -391,34 +391,21 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
/**
* {@code other}是否与当前区间不相交
*
* @param other 另一区间
* @param other 另一区间
* @return 是否
*/
public boolean isDisjoint(final BoundedRange<T> other) {
return getLowerBound().compareTo(other.getUpperBound()) > 0
|| getUpperBound().compareTo(other.getLowerBound()) < 0;
return BoundedRangeOperation.isDisjoint(this, other);
}
/**
* {@code other}是否与当前区间相交:
*
* @param other 另一区间
* @param other 另一区间
* @return 是否
*/
public boolean isIntersected(final BoundedRange<T> other) {
return !isDisjoint(other);
}
/**
* {@code other}与当前区间是否相等
*
* @param other 另一区间
* @return 是否
*/
public boolean isEquals(final BoundedRange<T> other) {
Objects.requireNonNull(other);
return other.getLowerBound().compareTo(getLowerBound()) == 0
&& other.getUpperBound().compareTo(getUpperBound()) == 0;
return BoundedRangeOperation.isIntersected(this, other);
}
/**
@@ -441,7 +428,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
/**
* 若{@code other}与当前区间相交,则将其与当前区间合并。
*
* @param other 另一区间
* @param other 另一区间
* @return 合并后的新区间,若两区间不相交则返回当前集合
*/
public BoundedRange<T> unionIfIntersected(final BoundedRange<T> other) {

View File

@@ -150,8 +150,9 @@ public class BoundedRangeOperation {
.orElse(boundedRange);
}
// region ========== 判断交并集 ==========
/**
* {@code other}是否与当前区间相交
* {@code boundedRange}是否与{@code other}相交
*
* @param <T> 可比较对象类型
* @param boundedRange 区间
@@ -163,7 +164,7 @@ public class BoundedRangeOperation {
}
/**
* {@code other}是否与当前区间不相交
* {@code boundedRange}是否与{@code other}前区间不相交
*
* @param <T> 可比较对象类型
* @param boundedRange 区间
@@ -176,4 +177,5 @@ public class BoundedRangeOperation {
return boundedRange.getLowerBound().compareTo(other.getUpperBound()) > 0
|| boundedRange.getUpperBound().compareTo(other.getLowerBound()) < 0;
}
// endregion
}

View File

@@ -1,6 +1,7 @@
package cn.hutool.core.lang.range;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjUtil;
import java.util.Objects;
@@ -93,31 +94,13 @@ class FiniteBound<T extends Comparable<? super T>> implements Bound<T> {
return -1;
}
// 两值不相等,直接比较边界值
if (!Objects.equals(getValue(), bound.getValue())) {
if (ObjUtil.notEquals(getValue(), bound.getValue())) {
return getValue().compareTo(bound.getValue());
}
// 两边界值相等
return compareIfSameBoundValue(bound);
}
/**
* 当两个边界的值不相等时,判断它们在坐标轴上位置的先后顺序
*/
private int compareIfSameBoundValue(final Bound<T> bound) {
final BoundType bt1 = this.getType();
final BoundType bt2 = bound.getType();
// 两边界类型相同,说明连边界重合
if (bt1 == bt2) {
return 0;
}
// 一为左边界,一为右边界,则左边界恒在右边界后
if (bt1.isDislocated(bt2)) {
return bt1.isLowerBound() ? 1 : -1;
}
// 都为左边界,则封闭边界在前,若都为右边界,则封闭边界在后
return Integer.compare(bt1.getCode(), bt2.getCode());
}
/**
* 获取{@code "[value"}或{@code "(value"}格式的字符串
*
@@ -189,4 +172,22 @@ class FiniteBound<T extends Comparable<? super T>> implements Bound<T> {
"{x | x {} {}}", type.getOperator(), value
);
}
/**
* 当两个边界的值不相等时,判断它们在坐标轴上位置的先后顺序
*/
private int compareIfSameBoundValue(final Bound<T> bound) {
final BoundType bt1 = this.getType();
final BoundType bt2 = bound.getType();
// 两边界类型相同,说明连边界重合
if (bt1 == bt2) {
return 0;
}
// 一为左边界,一为右边界,则左边界恒在右边界后
if (bt1.isDislocated(bt2)) {
return bt1.isLowerBound() ? 1 : -1;
}
// 都为左边界,则封闭边界在前,若都为右边界,则封闭边界在后
return Integer.compare(bt1.getCode(), bt2.getCode());
}
}

View File

@@ -1,5 +1,6 @@
package cn.hutool.core.math;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
@@ -946,78 +947,6 @@ public class NumberUtil {
return Long.parseLong(binaryStr, 2);
}
/**
* 检查值是否在指定范围内
*
* @param value 值
* @param minInclude 最小值(包含)
* @param maxInclude 最大值(包含)
* @return 经过检查后的值
* @since 5.8.5
*/
public static boolean isIn(final BigDecimal value, final BigDecimal minInclude, final BigDecimal maxInclude) {
Assert.notNull(value);
Assert.notNull(minInclude);
Assert.notNull(maxInclude);
return isGreaterOrEqual(value, minInclude) && isLessOrEqual(value, maxInclude);
}
/**
* 比较大小参数1 &gt; 参数2 返回true
*
* @param bigNum1 数字1
* @param bigNum2 数字2
* @return 是否大于
* @since 3.0.9
*/
public static boolean isGreater(final BigDecimal bigNum1, final BigDecimal bigNum2) {
Assert.notNull(bigNum1);
Assert.notNull(bigNum2);
return bigNum1.compareTo(bigNum2) > 0;
}
/**
* 比较大小参数1 &gt;= 参数2 返回true
*
* @param bigNum1 数字1
* @param bigNum2 数字2
* @return 是否大于等于
* @since 3, 0.9
*/
public static boolean isGreaterOrEqual(final BigDecimal bigNum1, final BigDecimal bigNum2) {
Assert.notNull(bigNum1);
Assert.notNull(bigNum2);
return bigNum1.compareTo(bigNum2) >= 0;
}
/**
* 比较大小参数1 &lt; 参数2 返回true
*
* @param bigNum1 数字1
* @param bigNum2 数字2
* @return 是否小于
* @since 3, 0.9
*/
public static boolean isLess(final BigDecimal bigNum1, final BigDecimal bigNum2) {
Assert.notNull(bigNum1);
Assert.notNull(bigNum2);
return bigNum1.compareTo(bigNum2) < 0;
}
/**
* 比较大小参数1&lt;=参数2 返回true
*
* @param bigNum1 数字1
* @param bigNum2 数字2
* @return 是否小于等于
* @since 3, 0.9
*/
public static boolean isLessOrEqual(final BigDecimal bigNum1, final BigDecimal bigNum2) {
Assert.notNull(bigNum1);
Assert.notNull(bigNum2);
return bigNum1.compareTo(bigNum2) <= 0;
}
/**
* 比较大小,值相等 返回true<br>
* 此方法通过调用{@link Double#doubleToLongBits(double)}方法来判断是否相等<br>
@@ -1067,17 +996,10 @@ public class NumberUtil {
* @param bigNum1 数字1
* @param bigNum2 数字2
* @return 是否相等
* @see CompareUtil#equals(Comparable, Comparable)
*/
public static boolean equals(final BigDecimal bigNum1, final BigDecimal bigNum2) {
//noinspection NumberEquality
if (bigNum1 == bigNum2) {
// 如果用户传入同一对象省略compareTo以提高性能。
return true;
}
if (bigNum1 == null || bigNum2 == null) {
return false;
}
return 0 == bigNum1.compareTo(bigNum2);
return CompareUtil.equals(bigNum1, bigNum2);
}
/**

View File

@@ -54,8 +54,8 @@ public class BoundedRangeTest {
// isXXX
Assert.assertFalse(range.isDisjoint(BoundedRange.open(0, 5)));
Assert.assertTrue(range.isEquals(range));
Assert.assertFalse(range.isEquals(BoundedRange.open(0, 5)));
Assert.assertEquals(range, range);
Assert.assertNotEquals(range, BoundedRange.open(0, 5));
Assert.assertTrue(range.isIntersected(BoundedRange.open(0, 5)));
Assert.assertTrue(range.isIntersected(range));
Assert.assertFalse(range.isSubset(BoundedRange.open(0, 5)));
@@ -101,7 +101,7 @@ public class BoundedRangeTest {
Assert.assertFalse(range.test(-1));
// isXXX
Assert.assertTrue(range.isEquals(range));
Assert.assertEquals(range, range);
Assert.assertTrue(range.isDisjoint(BoundedRange.open(-5, 0))); // (-5, 0)
Assert.assertTrue(range.isDisjoint(BoundedRange.close(-5, 0))); // [-5, 0]
Assert.assertTrue(range.isIntersected(BoundedRange.close(-5, 1))); // [-5, 1]
@@ -142,7 +142,7 @@ public class BoundedRangeTest {
Assert.assertFalse(range.test(-1));
// isXXX
Assert.assertTrue(range.isEquals(range));
Assert.assertEquals(range, range);
Assert.assertTrue(range.isDisjoint(BoundedRange.open(-5, 0))); // (-5, 0)
Assert.assertTrue(range.isDisjoint(BoundedRange.close(-5, 0))); // [-5, 0]
Assert.assertTrue(range.isIntersected(BoundedRange.open(-5, 1))); // [-5, 1]