This commit is contained in:
Looly 2022-10-08 19:30:43 +08:00
parent da33cf4c06
commit 45c87bd1ff
8 changed files with 439 additions and 287 deletions

View File

@ -24,6 +24,13 @@ import java.util.Set;
*/
public class CollectionOperation<E> {
/**
* 创建运算对象
*
* @param colls 集合列表
* @param <E> 元素类型
* @return CollectionOperation
*/
@SafeVarargs
public static <E> CollectionOperation<E> of(final Collection<E>... colls) {
return new CollectionOperation<>(colls);
@ -160,14 +167,14 @@ public class CollectionOperation<E> {
// 任意容器为空, 则返回空集
for (final Collection<E> coll : colls) {
if(CollUtil.isEmpty(coll)){
if (CollUtil.isEmpty(coll)) {
return SetUtil.zeroLinked();
}
}
final Set<E> 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<E> {
*/
public List<E> subtract() {
final Collection<E>[] colls = this.colls;
if(ArrayUtil.isEmpty(colls)){
if (ArrayUtil.isEmpty(colls)) {
return ListUtil.zero();
}
final List<E> result = ListUtil.of(colls[0]);
@ -226,6 +233,7 @@ public class CollectionOperation<E> {
}
// region private methods
/**
* 两个集合的并集<br>
* 针对一个集合中存在多个相同元素的情况计算两个集合中此元素的个数保留最多的个数<br>
@ -315,12 +323,12 @@ public class CollectionOperation<E> {
* @return 差集的集合返回 {@link ArrayList}
*/
private static <T> Collection<T> _disjunction(final Collection<T> coll1, final Collection<T> 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;
}

View File

@ -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<T extends Comparable<? super T>> extends Predicate<T>, Co
*/
@Override
String toString();
/**
* 由一个有限值构成的边界
*
* @param <T> 边界值类型
*/
class FiniteBound<T extends Comparable<? super T>> implements Bound<T> {
/**
* 边界值
*/
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();
}
/**
* <p>比较另一边界与当前边界在坐标轴上位置的先后顺序<br>
* 若令当前边界为<em>t1</em>另一边界为<em>t2</em>则有
* <ul>
* <li>-1<em>t1</em><em>t2</em>的左侧</li>
* <li>0<em>t1</em><em>t2</em>的重合</li>
* <li>-1<em>t1</em><em>t2</em>的右侧</li>
* </ul>
*
* @param bound 边界
* @return 位置
*/
@Override
public int compareTo(final Bound<T> 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<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"}格式的字符串
*
* @return 字符串
*/
@Override
public String descBound() {
final BoundType bt = getType();
return bt.isLowerBound() ? bt.getSymbol() + getValue() : getValue() + bt.getSymbol();
}
/**
* 对当前边界取反
*
* @return 取反后的边界
*/
@Override
public Bound<T> negate() {
return new FiniteBound<>(value, getType().negate());
}
/**
* 将当前实例转为一个区间
*
* @return 区间
*/
@Override
public BoundedRange<T> 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
);
}
}
}

View File

@ -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<T extends Comparable<? super T>> implements Predicate<
@SuppressWarnings({"rawtypes", "unchecked"})
private static final BoundedRange ALL = new BoundedRange(Bound.noneLowerBound(), Bound.noneUpperBound());
/**
* 下界
*/
private final Bound<T> lowerBound;
/**
* 上界
*/
private final Bound<T> upperBound;
/**
* 构建一个上下界皆无限大的区间{@code {x | - < x < +}}
*
* @param <T> 比较对象类型
* @return 区间
*/
@SuppressWarnings("unchecked")
static <T extends Comparable<? super T>> BoundedRange<T> all() {
public static <T extends Comparable<? super T>> BoundedRange<T> all() {
return ALL;
}
@ -83,7 +72,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出
* @throws NullPointerException 上界或下界为{@code null}时抛出
*/
static <T extends Comparable<? super T>> BoundedRange<T> close(final T lowerBound, final T upperBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> close(final T lowerBound, final T upperBound) {
Objects.requireNonNull(lowerBound);
Objects.requireNonNull(upperBound);
return checkEmpty(
@ -103,7 +92,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出
* @throws NullPointerException 上界或下界为{@code null}时抛出
*/
static <T extends Comparable<? super T>> BoundedRange<T> open(final T lowerBound, final T upperBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> open(final T lowerBound, final T upperBound) {
Objects.requireNonNull(lowerBound);
Objects.requireNonNull(upperBound);
return checkEmpty(
@ -121,7 +110,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出
* @throws NullPointerException 上界或下界为{@code null}时抛出
*/
static <T extends Comparable<? super T>> BoundedRange<T> closeOpen(final T lowerBound, final T upperBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> closeOpen(final T lowerBound, final T upperBound) {
Objects.requireNonNull(lowerBound);
Objects.requireNonNull(upperBound);
return checkEmpty(
@ -142,7 +131,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws IllegalArgumentException 当创建的区间表示的集合为空时抛出
* @throws NullPointerException 上界或下界为{@code null}时抛出
*/
static <T extends Comparable<? super T>> BoundedRange<T> openClose(final T lowerBound, final T upperBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> openClose(final T lowerBound, final T upperBound) {
Objects.requireNonNull(lowerBound);
Objects.requireNonNull(upperBound);
return checkEmpty(
@ -162,7 +151,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws NullPointerException 下界为{@code null}时抛出
* @see Bound#toRange()
*/
static <T extends Comparable<? super T>> BoundedRange<T> greaterThan(final T lowerBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> greaterThan(final T lowerBound) {
return Bound.greaterThan(lowerBound).toRange();
}
@ -175,7 +164,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws NullPointerException 下界为{@code null}时抛出
* @see Bound#toRange()
*/
static <T extends Comparable<? super T>> BoundedRange<T> atLeast(final T lowerBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> atLeast(final T lowerBound) {
return Bound.atLeast(lowerBound).toRange();
}
@ -188,7 +177,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws NullPointerException 上界为{@code null}时抛出
* @see Bound#toRange()
*/
static <T extends Comparable<? super T>> BoundedRange<T> lessThan(final T upperBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> lessThan(final T upperBound) {
return Bound.lessThan(upperBound).toRange();
}
@ -201,10 +190,20 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @throws NullPointerException 上界为{@code null}时抛出
* @see Bound#toRange()
*/
static <T extends Comparable<? super T>> BoundedRange<T> atMost(final T upperBound) {
public static <T extends Comparable<? super T>> BoundedRange<T> atMost(final T upperBound) {
return Bound.atMost(upperBound).toRange();
}
/**
* 下界
*/
private final Bound<T> lowerBound;
/**
* 上界
*/
private final Bound<T> upperBound;
/**
* 构造
*
@ -446,62 +445,37 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
* @return 合并后的新区间若两区间不相交则返回当前集合
*/
public BoundedRange<T> unionIfIntersected(final BoundedRange<T> 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<T> span(final BoundedRange<T> 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<T> gap(final BoundedRange<T> 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<T> intersection(final BoundedRange<T> 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<T extends Comparable<? super T>> implements Predicate<
* @return 区间
*/
public BoundedRange<T> 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<T extends Comparable<? super T>> implements Predicate<
* @return 区间
*/
public BoundedRange<T> 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<T extends Comparable<? super T>> implements Predicate<
* @return 区间
*/
public BoundedRange<T> 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<T extends Comparable<? super T>> implements Predicate<
* @return 区间
*/
public BoundedRange<T> 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

View File

@ -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 <T> 可比较对象类型
* @param boundedRange 区间
* @param other 另一个区间
* @return 合并后的新区间若两区间不相交则返回当前集合
*/
public static <T extends Comparable<? super T>> BoundedRange<T> unionIfIntersected(final BoundedRange<T> boundedRange, final BoundedRange<T> 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 <T> 可比较对象类型
* @param boundedRange 区间
* @param other 另一个区间
* @return 包含当前区间与指定区间的最小的区间
*/
public static <T extends Comparable<? super T>> BoundedRange<T> span(final BoundedRange<T> boundedRange, final BoundedRange<T> 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 <T> 可比较对象类型
* @param boundedRange 区间
* @param other 另一个区间
* @return 代表间隔部分的区间若两区间相交则返回{@code null}
*/
public static <T extends Comparable<? super T>> BoundedRange<T> gap(final BoundedRange<T> boundedRange, final BoundedRange<T> 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 <T> 可比较对象类型
* @param boundedRange 区间
* @param other 另一个区间
* @return 代表交集的区间若无交集则返回{@code null}
*/
public static <T extends Comparable<? super T>> BoundedRange<T> intersection(final BoundedRange<T> boundedRange, final BoundedRange<T> 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 <T> 可比较对象类型
* @param boundedRange 区间
* @param min 最大的左值
* @return 区间
*/
public static <T extends Comparable<? super T>> BoundedRange<T> subGreatThan(final BoundedRange<T> 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 <T> 可比较对象类型
* @param boundedRange 区间
* @param min 最大的左值
* @return 区间
*/
public static <T extends Comparable<? super T>> BoundedRange<T> subAtLeast(final BoundedRange<T> 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 <T> 可比较对象类型
* @param boundedRange 区间
* @param max 最大的左值
* @return 区间
*/
public static <T extends Comparable<? super T>> BoundedRange<T> subLessThan(final BoundedRange<T> 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 <T> 可比较对象类型
* @param boundedRange 区间
* @param max 最大的左值
* @return 区间
*/
public static <T extends Comparable<? super T>> BoundedRange<T> subAtMost(final BoundedRange<T> boundedRange, final T max) {
return Opt.ofNullable(max)
.filter(boundedRange)
.map(t -> new BoundedRange<>(boundedRange.getLowerBound(), Bound.atMost(max)))
.orElse(boundedRange);
}
/**
* {@code other}是否与当前区间相交
*
* @param <T> 可比较对象类型
* @param boundedRange 区间
* @param other 另一个区间
* @return 是否相交
*/
public static <T extends Comparable<? super T>> boolean isIntersected(final BoundedRange<T> boundedRange, final BoundedRange<T> other) {
return false == isDisjoint(boundedRange, other);
}
/**
* {@code other}是否与当前区间不相交
*
* @param <T> 可比较对象类型
* @param boundedRange 区间
* @param other 另一个区间
* @return 是否
*/
public static <T extends Comparable<? super T>> boolean isDisjoint(final BoundedRange<T> boundedRange, final BoundedRange<T> other) {
Objects.requireNonNull(boundedRange);
Objects.requireNonNull(other);
return boundedRange.getLowerBound().compareTo(other.getUpperBound()) > 0
|| boundedRange.getUpperBound().compareTo(other.getLowerBound()) < 0;
}
}

View File

@ -0,0 +1,192 @@
package cn.hutool.core.lang.range;
import cn.hutool.core.text.CharSequenceUtil;
import java.util.Objects;
/**
* 由一个有限值构成的边界
*
* @param <T> 边界值类型
*/
class FiniteBound<T extends Comparable<? super T>> implements Bound<T> {
/**
* 边界值
*/
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();
}
/**
* <p>比较另一边界与当前边界在坐标轴上位置的先后顺序<br>
* 若令当前边界为<em>t1</em>另一边界为<em>t2</em>则有
* <ul>
* <li>-1<em>t1</em><em>t2</em>的左侧</li>
* <li>0<em>t1</em><em>t2</em>的重合</li>
* <li>-1<em>t1</em><em>t2</em>的右侧</li>
* </ul>
*
* @param bound 边界
* @return 位置
*/
@Override
public int compareTo(final Bound<T> 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<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"}格式的字符串
*
* @return 字符串
*/
@Override
public String descBound() {
final BoundType bt = getType();
return bt.isLowerBound() ? bt.getSymbol() + getValue() : getValue() + bt.getSymbol();
}
/**
* 对当前边界取反
*
* @return 取反后的边界
*/
@Override
public Bound<T> negate() {
return new FiniteBound<>(value, getType().negate());
}
/**
* 将当前实例转为一个区间
*
* @return 区间
*/
@Override
public BoundedRange<T> 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
);
}
}

View File

@ -6,29 +6,30 @@ import org.junit.Test;
/**
* test for {@link Bound}
*/
@SuppressWarnings("EqualsWithItself")
public class BoundTest {
@Test
public void testEquals() {
Bound<Integer> bound = new Bound.FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND);
final Bound<Integer> 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<Integer> bound = Bound.noneLowerBound();
final Bound<Integer> bound = Bound.noneLowerBound();
// negate
Assert.assertEquals(bound, bound.negate());
// test
@ -49,7 +50,7 @@ public class BoundTest {
@Test
public void testNoneUpperBound() {
Bound<Integer> bound = Bound.noneUpperBound();
final Bound<Integer> bound = Bound.noneUpperBound();
// negate
Assert.assertEquals(bound, bound.negate());
// test

View File

@ -10,7 +10,7 @@ public class BoundedRangeTest {
@Test
public void testEquals() {
BoundedRange<Integer> range = new BoundedRange<>(
final BoundedRange<Integer> 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<Integer> range = BoundedRange.all();
final BoundedRange<Integer> range = BoundedRange.all();
Assert.assertEquals("(-∞, +∞)", range.toString());
// getBound
@ -83,7 +83,7 @@ public class BoundedRangeTest {
@Test
public void testOpen() {
BoundedRange<Integer> range = BoundedRange.open(0, 5);
final BoundedRange<Integer> range = BoundedRange.open(0, 5);
Assert.assertEquals("(0, 5)", range.toString());
// getBound
@ -125,7 +125,7 @@ public class BoundedRangeTest {
@Test
public void testClose() {
BoundedRange<Integer> range = BoundedRange.close(0, 5);
final BoundedRange<Integer> range = BoundedRange.close(0, 5);
Assert.assertEquals("[0, 5]", range.toString());
// getBound
@ -168,7 +168,7 @@ public class BoundedRangeTest {
@Test
public void testOpenClose() {
BoundedRange<Integer> range = BoundedRange.openClose(0, 5);
final BoundedRange<Integer> range = BoundedRange.openClose(0, 5);
Assert.assertEquals("(0, 5]", range.toString());
// getBound
@ -187,7 +187,7 @@ public class BoundedRangeTest {
@Test
public void testCloseOpen() {
BoundedRange<Integer> range = BoundedRange.closeOpen(0, 5);
final BoundedRange<Integer> range = BoundedRange.closeOpen(0, 5);
Assert.assertEquals("[0, 5)", range.toString());
// getBound
@ -206,7 +206,7 @@ public class BoundedRangeTest {
@Test
public void testGreatThan() {
BoundedRange<Integer> range = BoundedRange.greaterThan(0);
final BoundedRange<Integer> range = BoundedRange.greaterThan(0);
Assert.assertEquals("(0, +∞)", range.toString());
// getBound
@ -225,7 +225,7 @@ public class BoundedRangeTest {
@Test
public void testAtLeast() {
BoundedRange<Integer> range = BoundedRange.atLeast(0);
final BoundedRange<Integer> range = BoundedRange.atLeast(0);
Assert.assertEquals("[0, +∞)", range.toString());
// getBound
@ -244,7 +244,7 @@ public class BoundedRangeTest {
@Test
public void testLessThan() {
BoundedRange<Integer> range = BoundedRange.lessThan(5);
final BoundedRange<Integer> range = BoundedRange.lessThan(5);
Assert.assertEquals("(-∞, 5)", range.toString());
// getBound
@ -263,7 +263,7 @@ public class BoundedRangeTest {
@Test
public void testAtMost() {
BoundedRange<Integer> range = BoundedRange.atMost(5);
final BoundedRange<Integer> range = BoundedRange.atMost(5);
Assert.assertEquals("(-∞, 5]", range.toString());
// getBound

View File

@ -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;