diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java index 7e1a97ce6..c9ddfe34f 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java @@ -24,6 +24,13 @@ import java.util.Set; */ public class CollectionOperation { + /** + * 创建运算对象 + * + * @param colls 集合列表 + * @param 元素类型 + * @return CollectionOperation + */ @SafeVarargs public static CollectionOperation of(final Collection... colls) { return new CollectionOperation<>(colls); @@ -160,14 +167,14 @@ public class CollectionOperation { // 任意容器为空, 则返回空集 for (final Collection coll : colls) { - if(CollUtil.isEmpty(coll)){ + if (CollUtil.isEmpty(coll)) { return SetUtil.zeroLinked(); } } final Set result = SetUtil.of(true, colls[0]); for (int i = 1; i < colls.length; i++) { - if(CollUtil.isNotEmpty(colls[i])){ + if (CollUtil.isNotEmpty(colls[i])) { result.retainAll(colls[i]); } } @@ -215,7 +222,7 @@ public class CollectionOperation { */ public List subtract() { final Collection[] colls = this.colls; - if(ArrayUtil.isEmpty(colls)){ + if (ArrayUtil.isEmpty(colls)) { return ListUtil.zero(); } final List result = ListUtil.of(colls[0]); @@ -226,6 +233,7 @@ public class CollectionOperation { } // region private methods + /** * 两个集合的并集
* 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留最多的个数
@@ -315,12 +323,12 @@ public class CollectionOperation { * @return 差集的集合,返回 {@link ArrayList} */ private static Collection _disjunction(final Collection coll1, final Collection coll2) { - if(CollUtil.isEmpty(coll1)){ - if(CollUtil.isEmpty(coll2)){ + if (CollUtil.isEmpty(coll1)) { + if (CollUtil.isEmpty(coll2)) { return ListUtil.zero(); } return coll2; - } else if(CollUtil.isEmpty(coll2)){ + } else if (CollUtil.isEmpty(coll2)) { return coll1; } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java index c26a559b7..b17f51234 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java @@ -1,7 +1,5 @@ package cn.hutool.core.lang.range; -import cn.hutool.core.text.CharSequenceUtil; - import java.util.Objects; import java.util.function.Predicate; @@ -187,191 +185,4 @@ public interface Bound> extends Predicate, Co */ @Override String toString(); - - /** - * 由一个有限值构成的边界 - * - * @param 边界值类型 - */ - class FiniteBound> implements Bound { - - /** - * 边界值 - */ - private final T value; - - /** - * 边界类型 - */ - private final BoundType type; - - /** - * 构造 - * - * @param value 边界值 - * @param type 边界类型 - */ - FiniteBound(final T value, final BoundType type) { - this.value = value; - this.type = type; - } - - /** - * 获取边界值 - * - * @return 边界值 - */ - @Override - public T getValue() { - return value; - } - - /** - * 获取边界类型 - * - * @return 边界类型 - */ - @Override - public BoundType getType() { - return type; - } - - /** - * 检验指定值是否在当前边界表示的范围内 - * - * @param t 要检验的值,不允许为{@code null} - * @return 是否 - */ - @Override - public boolean test(final T t) { - final BoundType bt = this.getType(); - final int compareValue = getValue().compareTo(t); - // 与边界值相等 - if (compareValue == 0) { - return bt.isClose(); - } - // 小于或大于边界值 - return compareValue > 0 ? bt.isUpperBound() : bt.isLowerBound(); - } - - /** - *

比较另一边界与当前边界在坐标轴上位置的先后顺序。
- * 若令当前边界为t1,另一边界为t2,则有 - *

    - *
  • -1:t1t2的左侧;
  • - *
  • 0:t1t2的重合;
  • - *
  • -1:t1t2的右侧;
  • - *
- * - * @param bound 边界 - * @return 位置 - */ - @Override - public int compareTo(final Bound bound) { - // 另一边界为无限小的左边界,则当前边界必然靠后 - if (bound instanceof NoneLowerBound) { - return 1; - } - // 另一边界为无限大的右边界,则当前边界必然靠前 - if (bound instanceof NoneUpperBound) { - return -1; - } - // 两值不相等,直接比较边界值 - if (!Objects.equals(getValue(), bound.getValue())) { - return getValue().compareTo(bound.getValue()); - } - // 两边界值相等 - return compareIfSameBoundValue(bound); - } - - /** - * 当两个边界的值不相等时,判断它们在坐标轴上位置的先后顺序 - */ - private int compareIfSameBoundValue(final Bound 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"}格式的字符串 - * - * @return 字符串 - */ - @Override - public String descBound() { - final BoundType bt = getType(); - return bt.isLowerBound() ? bt.getSymbol() + getValue() : getValue() + bt.getSymbol(); - } - - /** - * 对当前边界取反 - * - * @return 取反后的边界 - */ - @Override - public Bound negate() { - return new FiniteBound<>(value, getType().negate()); - } - - /** - * 将当前实例转为一个区间 - * - * @return 区间 - */ - @Override - public BoundedRange toRange() { - return getType().isLowerBound() ? - new BoundedRange<>(this, Bound.noneUpperBound()) : new BoundedRange<>(Bound.noneLowerBound(), this); - } - - /** - * 两实例是否相等 - * - * @param o 另一实例 - * @return 是否 - */ - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final FiniteBound that = (FiniteBound)o; - return value.equals(that.value) && type == that.type; - } - - /** - * 获取哈希值 - * - * @return 哈希值 - */ - @Override - public int hashCode() { - return Objects.hash(value, type); - } - - /** - * 获得当前实例对应的{@code {x| x >= xxx}}格式的不等式字符串 - * - * @return 字符串 - */ - @Override - public String toString() { - return CharSequenceUtil.format( - "{x | x {} {}}", type.getOperator(), value - ); - } - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java index 5992c7754..5660f7800 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java @@ -1,8 +1,6 @@ package cn.hutool.core.lang.range; -import cn.hutool.core.comparator.CompareUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Opt; import java.util.Objects; import java.util.function.Predicate; @@ -53,23 +51,14 @@ public class BoundedRange> implements Predicate< @SuppressWarnings({"rawtypes", "unchecked"}) private static final BoundedRange ALL = new BoundedRange(Bound.noneLowerBound(), Bound.noneUpperBound()); - /** - * 下界 - */ - private final Bound lowerBound; - - /** - * 上界 - */ - private final Bound upperBound; - /** * 构建一个上下界皆无限大的区间,即{@code {x | -∞ < x < +∞}} * + * @param 比较对象类型 * @return 区间 */ @SuppressWarnings("unchecked") - static > BoundedRange all() { + public static > BoundedRange all() { return ALL; } @@ -83,7 +72,7 @@ public class BoundedRange> implements Predicate< * @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出 * @throws NullPointerException 上界或下界为{@code null}时抛出 */ - static > BoundedRange close(final T lowerBound, final T upperBound) { + public static > BoundedRange close(final T lowerBound, final T upperBound) { Objects.requireNonNull(lowerBound); Objects.requireNonNull(upperBound); return checkEmpty( @@ -103,7 +92,7 @@ public class BoundedRange> implements Predicate< * @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出 * @throws NullPointerException 上界或下界为{@code null}时抛出 */ - static > BoundedRange open(final T lowerBound, final T upperBound) { + public static > BoundedRange open(final T lowerBound, final T upperBound) { Objects.requireNonNull(lowerBound); Objects.requireNonNull(upperBound); return checkEmpty( @@ -121,7 +110,7 @@ public class BoundedRange> implements Predicate< * @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出 * @throws NullPointerException 上界或下界为{@code null}时抛出 */ - static > BoundedRange closeOpen(final T lowerBound, final T upperBound) { + public static > BoundedRange closeOpen(final T lowerBound, final T upperBound) { Objects.requireNonNull(lowerBound); Objects.requireNonNull(upperBound); return checkEmpty( @@ -142,7 +131,7 @@ public class BoundedRange> implements Predicate< * @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出 * @throws NullPointerException 上界或下界为{@code null}时抛出 */ - static > BoundedRange openClose(final T lowerBound, final T upperBound) { + public static > BoundedRange openClose(final T lowerBound, final T upperBound) { Objects.requireNonNull(lowerBound); Objects.requireNonNull(upperBound); return checkEmpty( @@ -162,7 +151,7 @@ public class BoundedRange> implements Predicate< * @throws NullPointerException 下界为{@code null}时抛出 * @see Bound#toRange() */ - static > BoundedRange greaterThan(final T lowerBound) { + public static > BoundedRange greaterThan(final T lowerBound) { return Bound.greaterThan(lowerBound).toRange(); } @@ -175,7 +164,7 @@ public class BoundedRange> implements Predicate< * @throws NullPointerException 下界为{@code null}时抛出 * @see Bound#toRange() */ - static > BoundedRange atLeast(final T lowerBound) { + public static > BoundedRange atLeast(final T lowerBound) { return Bound.atLeast(lowerBound).toRange(); } @@ -188,7 +177,7 @@ public class BoundedRange> implements Predicate< * @throws NullPointerException 上界为{@code null}时抛出 * @see Bound#toRange() */ - static > BoundedRange lessThan(final T upperBound) { + public static > BoundedRange lessThan(final T upperBound) { return Bound.lessThan(upperBound).toRange(); } @@ -201,10 +190,20 @@ public class BoundedRange> implements Predicate< * @throws NullPointerException 上界为{@code null}时抛出 * @see Bound#toRange() */ - static > BoundedRange atMost(final T upperBound) { + public static > BoundedRange atMost(final T upperBound) { return Bound.atMost(upperBound).toRange(); } + /** + * 下界 + */ + private final Bound lowerBound; + + /** + * 上界 + */ + private final Bound upperBound; + /** * 构造 * @@ -446,62 +445,37 @@ public class BoundedRange> implements Predicate< * @return 合并后的新区间,若两区间不相交则返回当前集合 */ public BoundedRange unionIfIntersected(final BoundedRange other) { - Objects.requireNonNull(other); - if (isDisjoint(other)) { - return this; - } - return new BoundedRange<>( - CompareUtil.min(getLowerBound(), other.getLowerBound()), - CompareUtil.max(getUpperBound(), other.getUpperBound()) - ); + return BoundedRangeOperation.unionIfIntersected(this, other); } /** * 获得包含当前区间与指定区间的最小的区间 * - * @param other 另一区间 + * @param other 另一个区间 * @return 包含当前区间与指定区间的最小的区间 */ public BoundedRange span(final BoundedRange other) { - Objects.requireNonNull(other); - return new BoundedRange<>( - CompareUtil.min(getLowerBound(), other.getLowerBound()), - CompareUtil.max(getUpperBound(), other.getUpperBound()) - ); + return BoundedRangeOperation.span(this, other); } /** * 若{@code other}与当前区间不相连,则获得两区间中间的间隔部分 * - * @param other 另一区间 + * @param other 另一个区间 * @return 代表间隔部分的区间,若两区间相交则返回{@code null} */ public BoundedRange gap(final BoundedRange other) { - Objects.requireNonNull(other); - if (isIntersected(other)) { - return null; - } - return new BoundedRange<>( - CompareUtil.min(getUpperBound(), other.getUpperBound()).negate(), - CompareUtil.max(getLowerBound(), other.getLowerBound()).negate() - ); + return BoundedRangeOperation.gap(this, other); } /** * 若{@code other}与当前区间相交,则获得该区间与当前区间的交集 * - * @param other 另一区间 + * @param other 另一个区间 * @return 代表交集的区间,若无交集则返回{@code null} */ public BoundedRange intersection(final BoundedRange other) { - Objects.requireNonNull(other); - if (isDisjoint(other)) { - return null; - } - return new BoundedRange<>( - CompareUtil.min(getLowerBound(), other.getLowerBound()), - CompareUtil.max(getUpperBound(), other.getUpperBound()) - ); + return BoundedRangeOperation.intersection(this, other); } /** @@ -511,10 +485,7 @@ public class BoundedRange> implements Predicate< * @return 区间 */ public BoundedRange subGreatThan(final T min) { - return Opt.ofNullable(min) - .filter(this) - .map(t -> new BoundedRange<>(Bound.greaterThan(t), getUpperBound())) - .orElse(this); + return BoundedRangeOperation.subGreatThan(this, min); } /** @@ -524,10 +495,7 @@ public class BoundedRange> implements Predicate< * @return 区间 */ public BoundedRange subAtLeast(final T min) { - return Opt.ofNullable(min) - .filter(this) - .map(t -> new BoundedRange<>(Bound.atLeast(t), getUpperBound())) - .orElse(this); + return BoundedRangeOperation.subAtLeast(this, min); } /** @@ -537,10 +505,7 @@ public class BoundedRange> implements Predicate< * @return 区间 */ public BoundedRange subLessThan(final T max) { - return Opt.ofNullable(max) - .filter(this) - .map(t -> new BoundedRange<>(getLowerBound(), Bound.lessThan(max))) - .orElse(this); + return BoundedRangeOperation.subLessThan(this, max); } /** @@ -550,10 +515,7 @@ public class BoundedRange> implements Predicate< * @return 区间 */ public BoundedRange subAtMost(final T max) { - return Opt.ofNullable(max) - .filter(this) - .map(t -> new BoundedRange<>(getLowerBound(), Bound.atMost(max))) - .orElse(this); + return BoundedRangeOperation.subAtMost(this, max); } // endregion diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRangeOperation.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRangeOperation.java new file mode 100644 index 000000000..c7862b636 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRangeOperation.java @@ -0,0 +1,179 @@ +package cn.hutool.core.lang.range; + +import cn.hutool.core.comparator.CompareUtil; +import cn.hutool.core.lang.Opt; + +import java.util.Objects; + +/** + * 边界区间的操作工具,如子区间、合并区间等 + * + * @author huangchengxing + * @since 6.0.0 + */ +public class BoundedRangeOperation { + + /** + * 若{@code other}与当前区间相交,则将其与当前区间合并。 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param other 另一个区间 + * @return 合并后的新区间,若两区间不相交则返回当前集合 + */ + public static > BoundedRange unionIfIntersected(final BoundedRange boundedRange, final BoundedRange other) { + Objects.requireNonNull(boundedRange); + Objects.requireNonNull(other); + if (isDisjoint(boundedRange, other)) { + return boundedRange; + } + return new BoundedRange<>( + CompareUtil.min(boundedRange.getLowerBound(), other.getLowerBound()), + CompareUtil.max(boundedRange.getUpperBound(), other.getUpperBound()) + ); + } + + /** + * 获得包含当前区间与指定区间的最小的区间 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param other 另一个区间 + * @return 包含当前区间与指定区间的最小的区间 + */ + public static > BoundedRange span(final BoundedRange boundedRange, final BoundedRange other) { + Objects.requireNonNull(boundedRange); + Objects.requireNonNull(other); + return new BoundedRange<>( + CompareUtil.min(boundedRange.getLowerBound(), other.getLowerBound()), + CompareUtil.max(boundedRange.getUpperBound(), other.getUpperBound()) + ); + } + + /** + * 若{@code other}与当前区间不相连,则获得两区间中间的间隔部分 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param other 另一个区间 + * @return 代表间隔部分的区间,若两区间相交则返回{@code null} + */ + public static > BoundedRange gap(final BoundedRange boundedRange, final BoundedRange other) { + Objects.requireNonNull(boundedRange); + Objects.requireNonNull(other); + if (isIntersected(boundedRange, other)) { + return null; + } + return new BoundedRange<>( + CompareUtil.min(boundedRange.getUpperBound(), other.getUpperBound()).negate(), + CompareUtil.max(boundedRange.getLowerBound(), other.getLowerBound()).negate() + ); + } + + /** + * 若{@code other}与当前区间相交,则获得该区间与当前区间的交集 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param other 另一个区间 + * @return 代表交集的区间,若无交集则返回{@code null} + */ + public static > BoundedRange intersection(final BoundedRange boundedRange, final BoundedRange other) { + Objects.requireNonNull(boundedRange); + Objects.requireNonNull(other); + if (isDisjoint(boundedRange, other)) { + return null; + } + return new BoundedRange<>( + CompareUtil.max(boundedRange.getLowerBound(), other.getLowerBound()), + CompareUtil.min(boundedRange.getUpperBound(), other.getUpperBound()) + ); + } + + /** + * 截取当前区间中大于{@code min}的部分,若{@code min}不在该区间中,则返回当前区间本身 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param min 最大的左值 + * @return 区间 + */ + public static > BoundedRange subGreatThan(final BoundedRange boundedRange, final T min) { + return Opt.ofNullable(min) + .filter(boundedRange) + .map(t -> new BoundedRange<>(Bound.greaterThan(t), boundedRange.getUpperBound())) + .orElse(boundedRange); + } + + /** + * 截取当前区间中大于等于{@code min}的部分,若{@code min}不在该区间中,则返回当前区间本身 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param min 最大的左值 + * @return 区间 + */ + public static > BoundedRange subAtLeast(final BoundedRange boundedRange, final T min) { + return Opt.ofNullable(min) + .filter(boundedRange) + .map(t -> new BoundedRange<>(Bound.atLeast(t), boundedRange.getUpperBound())) + .orElse(boundedRange); + } + + /** + * 截取当前区间中小于{@code max}的部分,若{@code max}不在该区间中,则返回当前区间本身 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param max 最大的左值 + * @return 区间 + */ + public static > BoundedRange subLessThan(final BoundedRange boundedRange, final T max) { + return Opt.ofNullable(max) + .filter(boundedRange) + .map(t -> new BoundedRange<>(boundedRange.getLowerBound(), Bound.lessThan(max))) + .orElse(boundedRange); + } + + /** + * 截取当前区间中小于等于{@code max}的部分,若{@code max}不在该区间中,则返回当前区间本身 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param max 最大的左值 + * @return 区间 + */ + public static > BoundedRange subAtMost(final BoundedRange boundedRange, final T max) { + return Opt.ofNullable(max) + .filter(boundedRange) + .map(t -> new BoundedRange<>(boundedRange.getLowerBound(), Bound.atMost(max))) + .orElse(boundedRange); + } + + /** + * {@code other}是否与当前区间相交 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param other 另一个区间 + * @return 是否相交 + */ + public static > boolean isIntersected(final BoundedRange boundedRange, final BoundedRange other) { + return false == isDisjoint(boundedRange, other); + } + + /** + * {@code other}是否与当前区间不相交 + * + * @param 可比较对象类型 + * @param boundedRange 区间 + * @param other 另一个区间 + * @return 是否 + */ + public static > boolean isDisjoint(final BoundedRange boundedRange, final BoundedRange other) { + Objects.requireNonNull(boundedRange); + Objects.requireNonNull(other); + return boundedRange.getLowerBound().compareTo(other.getUpperBound()) > 0 + || boundedRange.getUpperBound().compareTo(other.getLowerBound()) < 0; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/FiniteBound.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/FiniteBound.java new file mode 100644 index 000000000..8ebd1d37e --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/FiniteBound.java @@ -0,0 +1,192 @@ +package cn.hutool.core.lang.range; + +import cn.hutool.core.text.CharSequenceUtil; + +import java.util.Objects; + +/** + * 由一个有限值构成的边界 + * + * @param 边界值类型 + */ +class FiniteBound> implements Bound { + + /** + * 边界值 + */ + private final T value; + + /** + * 边界类型 + */ + private final BoundType type; + + /** + * 构造 + * + * @param value 边界值 + * @param type 边界类型 + */ + FiniteBound(final T value, final BoundType type) { + this.value = value; + this.type = type; + } + + /** + * 获取边界值 + * + * @return 边界值 + */ + @Override + public T getValue() { + return value; + } + + /** + * 获取边界类型 + * + * @return 边界类型 + */ + @Override + public BoundType getType() { + return type; + } + + /** + * 检验指定值是否在当前边界表示的范围内 + * + * @param t 要检验的值,不允许为{@code null} + * @return 是否 + */ + @Override + public boolean test(final T t) { + final BoundType bt = this.getType(); + final int compareValue = getValue().compareTo(t); + // 与边界值相等 + if (compareValue == 0) { + return bt.isClose(); + } + // 小于或大于边界值 + return compareValue > 0 ? bt.isUpperBound() : bt.isLowerBound(); + } + + /** + *

比较另一边界与当前边界在坐标轴上位置的先后顺序。
+ * 若令当前边界为t1,另一边界为t2,则有 + *

    + *
  • -1:t1t2的左侧;
  • + *
  • 0:t1t2的重合;
  • + *
  • -1:t1t2的右侧;
  • + *
+ * + * @param bound 边界 + * @return 位置 + */ + @Override + public int compareTo(final Bound bound) { + // 另一边界为无限小的左边界,则当前边界必然靠后 + if (bound instanceof NoneLowerBound) { + return 1; + } + // 另一边界为无限大的右边界,则当前边界必然靠前 + if (bound instanceof NoneUpperBound) { + return -1; + } + // 两值不相等,直接比较边界值 + if (!Objects.equals(getValue(), bound.getValue())) { + return getValue().compareTo(bound.getValue()); + } + // 两边界值相等 + return compareIfSameBoundValue(bound); + } + + /** + * 当两个边界的值不相等时,判断它们在坐标轴上位置的先后顺序 + */ + private int compareIfSameBoundValue(final Bound 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"}格式的字符串 + * + * @return 字符串 + */ + @Override + public String descBound() { + final BoundType bt = getType(); + return bt.isLowerBound() ? bt.getSymbol() + getValue() : getValue() + bt.getSymbol(); + } + + /** + * 对当前边界取反 + * + * @return 取反后的边界 + */ + @Override + public Bound negate() { + return new FiniteBound<>(value, getType().negate()); + } + + /** + * 将当前实例转为一个区间 + * + * @return 区间 + */ + @Override + public BoundedRange toRange() { + return getType().isLowerBound() ? + new BoundedRange<>(this, Bound.noneUpperBound()) : new BoundedRange<>(Bound.noneLowerBound(), this); + } + + /** + * 两实例是否相等 + * + * @param o 另一实例 + * @return 是否 + */ + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final FiniteBound that = (FiniteBound)o; + return value.equals(that.value) && type == that.type; + } + + /** + * 获取哈希值 + * + * @return 哈希值 + */ + @Override + public int hashCode() { + return Objects.hash(value, type); + } + + /** + * 获得当前实例对应的{@code {x| x >= xxx}}格式的不等式字符串 + * + * @return 字符串 + */ + @Override + public String toString() { + return CharSequenceUtil.format( + "{x | x {} {}}", type.getOperator(), value + ); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java index a14f05ba2..0a7ea480e 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java @@ -6,29 +6,30 @@ import org.junit.Test; /** * test for {@link Bound} */ +@SuppressWarnings("EqualsWithItself") public class BoundTest { @Test public void testEquals() { - Bound bound = new Bound.FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND); + final Bound bound = new FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND); Assert.assertEquals(bound, bound); - Assert.assertEquals(bound, new Bound.FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND)); - Assert.assertNotEquals(bound, new Bound.FiniteBound<>(2, BoundType.OPEN_UPPER_BOUND)); - Assert.assertNotEquals(bound, new Bound.FiniteBound<>(1, BoundType.OPEN_LOWER_BOUND)); + Assert.assertEquals(bound, new FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND)); + Assert.assertNotEquals(bound, new FiniteBound<>(2, BoundType.OPEN_UPPER_BOUND)); + Assert.assertNotEquals(bound, new FiniteBound<>(1, BoundType.OPEN_LOWER_BOUND)); Assert.assertNotEquals(bound, null); } @Test public void testHashCode() { - int hashCode = new Bound.FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND).hashCode(); - Assert.assertEquals(hashCode, new Bound.FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND).hashCode()); - Assert.assertNotEquals(hashCode, new Bound.FiniteBound<>(2, BoundType.OPEN_UPPER_BOUND).hashCode()); - Assert.assertNotEquals(hashCode, new Bound.FiniteBound<>(1, BoundType.OPEN_LOWER_BOUND).hashCode()); + final int hashCode = new FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND).hashCode(); + Assert.assertEquals(hashCode, new FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND).hashCode()); + Assert.assertNotEquals(hashCode, new FiniteBound<>(2, BoundType.OPEN_UPPER_BOUND).hashCode()); + Assert.assertNotEquals(hashCode, new FiniteBound<>(1, BoundType.OPEN_LOWER_BOUND).hashCode()); } @Test public void testNoneLowerBound() { - Bound bound = Bound.noneLowerBound(); + final Bound bound = Bound.noneLowerBound(); // negate Assert.assertEquals(bound, bound.negate()); // test @@ -49,7 +50,7 @@ public class BoundTest { @Test public void testNoneUpperBound() { - Bound bound = Bound.noneUpperBound(); + final Bound bound = Bound.noneUpperBound(); // negate Assert.assertEquals(bound, bound.negate()); // test diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundedRangeTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundedRangeTest.java index f99dec051..fd1a67bba 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundedRangeTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundedRangeTest.java @@ -10,7 +10,7 @@ public class BoundedRangeTest { @Test public void testEquals() { - BoundedRange range = new BoundedRange<>( + final BoundedRange range = new BoundedRange<>( Bound.greaterThan(0), Bound.lessThan(10) ); Assert.assertEquals(range, range); @@ -25,7 +25,7 @@ public class BoundedRangeTest { @Test public void testHashCode() { - int hasCode = new BoundedRange<>( + final int hasCode = new BoundedRange<>( Bound.greaterThan(0), Bound.lessThan(10) ).hashCode(); Assert.assertEquals(hasCode, new BoundedRange<>( @@ -38,7 +38,7 @@ public class BoundedRangeTest { @Test public void testAll() { - BoundedRange range = BoundedRange.all(); + final BoundedRange range = BoundedRange.all(); Assert.assertEquals("(-∞, +∞)", range.toString()); // getBound @@ -83,7 +83,7 @@ public class BoundedRangeTest { @Test public void testOpen() { - BoundedRange range = BoundedRange.open(0, 5); + final BoundedRange range = BoundedRange.open(0, 5); Assert.assertEquals("(0, 5)", range.toString()); // getBound @@ -125,7 +125,7 @@ public class BoundedRangeTest { @Test public void testClose() { - BoundedRange range = BoundedRange.close(0, 5); + final BoundedRange range = BoundedRange.close(0, 5); Assert.assertEquals("[0, 5]", range.toString()); // getBound @@ -168,7 +168,7 @@ public class BoundedRangeTest { @Test public void testOpenClose() { - BoundedRange range = BoundedRange.openClose(0, 5); + final BoundedRange range = BoundedRange.openClose(0, 5); Assert.assertEquals("(0, 5]", range.toString()); // getBound @@ -187,7 +187,7 @@ public class BoundedRangeTest { @Test public void testCloseOpen() { - BoundedRange range = BoundedRange.closeOpen(0, 5); + final BoundedRange range = BoundedRange.closeOpen(0, 5); Assert.assertEquals("[0, 5)", range.toString()); // getBound @@ -206,7 +206,7 @@ public class BoundedRangeTest { @Test public void testGreatThan() { - BoundedRange range = BoundedRange.greaterThan(0); + final BoundedRange range = BoundedRange.greaterThan(0); Assert.assertEquals("(0, +∞)", range.toString()); // getBound @@ -225,7 +225,7 @@ public class BoundedRangeTest { @Test public void testAtLeast() { - BoundedRange range = BoundedRange.atLeast(0); + final BoundedRange range = BoundedRange.atLeast(0); Assert.assertEquals("[0, +∞)", range.toString()); // getBound @@ -244,7 +244,7 @@ public class BoundedRangeTest { @Test public void testLessThan() { - BoundedRange range = BoundedRange.lessThan(5); + final BoundedRange range = BoundedRange.lessThan(5); Assert.assertEquals("(-∞, 5)", range.toString()); // getBound @@ -263,7 +263,7 @@ public class BoundedRangeTest { @Test public void testAtMost() { - BoundedRange range = BoundedRange.atMost(5); + final BoundedRange range = BoundedRange.atMost(5); Assert.assertEquals("(-∞, 5]", range.toString()); // getBound diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/RangeTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/range/RangeTest.java similarity index 98% rename from hutool-core/src/test/java/cn/hutool/core/lang/RangeTest.java rename to hutool-core/src/test/java/cn/hutool/core/lang/range/RangeTest.java index 791dc890f..8bc27ea8c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/RangeTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/range/RangeTest.java @@ -1,10 +1,9 @@ -package cn.hutool.core.lang; +package cn.hutool.core.lang.range; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateRange; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.lang.range.Range; import cn.hutool.core.text.StrUtil; import org.junit.Assert; import org.junit.Test;