diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/FiniteBound.java b/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/FiniteBound.java index 2fbe5c53094eaf16f9776d2a177b6db0a9d2613b..e8ec3221e03c83353e7d46337e698fd7624ce45c 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/FiniteBound.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/FiniteBound.java @@ -200,8 +200,14 @@ class FiniteBound> implements Bound { if (bt1 == bt2) { return 0; } - // 一为左边界,一为右边界,则左边界恒在右边界后 + // 一为左边界,一为右边界 if (bt1.isDislocated(bt2)) { + // 特殊情况:右闭区间与左闭区间在同一点时,认为它们重合(用于区间相交判断) + if ((bt1 == BoundType.CLOSE_UPPER_BOUND && bt2 == BoundType.CLOSE_LOWER_BOUND) || + (bt1 == BoundType.CLOSE_LOWER_BOUND && bt2 == BoundType.CLOSE_UPPER_BOUND)) { + return 0; + } + // 一般情况:左边界恒在右边界后 return bt1.isLowerBound() ? 1 : -1; } // 都为左边界,则封闭边界在前,若都为右边界,则封闭边界在后 diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/Range.java b/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/Range.java index 397c5256f9ea1b73c6881f628d6c9a76f4ca0e0c..26a8cef8cc32fca67d965b32f996e793b2e71c18 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/Range.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/lang/range/Range.java @@ -165,6 +165,10 @@ public class Range implements Iterable, Serializable { * @return 下一步进 */ private T safeStep(final T base) { + // 添加边界检查 + if (base == null || (base.equals(end))) { + return null; + } final int index = this.index; T next = null; try { diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/lang/ref/PhantomObj.java b/hutool-core/src/main/java/cn/hutool/v7/core/lang/ref/PhantomObj.java index 1f130fb271da35ed6eab6450dfb55ad400b3d3ff..08ce961d23fbb7273fb6eeeb5dd2c73b685ca768 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/lang/ref/PhantomObj.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/lang/ref/PhantomObj.java @@ -52,7 +52,8 @@ public class PhantomObj extends PhantomReference implements Ref{ if (other == this) { return true; } else if (other instanceof PhantomObj) { - return ObjUtil.equals(((PhantomObj) other).get(), get()); + // 比较原始对象的哈希码,因为虚引用无法获取原始对象 + return this.hashCode == ((PhantomObj)other).hashCode; } return false; } diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/BoundTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/BoundTest.java index b400a0476e6d2bf9f05066c099fc58c678fbd864..6e698656613c2c69736d8c243b714aaa678e0853 100644 --- a/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/BoundTest.java +++ b/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/BoundTest.java @@ -17,14 +17,28 @@ package cn.hutool.v7.core.lang.range; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** * test for {@link Bound} */ @SuppressWarnings("EqualsWithItself") public class BoundTest { + @Test + @DisplayName("测试相邻区间合并") + void testUnionIfIntersectedWithAdjacentRanges() { + BoundedRange range1 = BoundedRange.close(1, 3); + BoundedRange range2 = BoundedRange.close(3, 5); + BoundedRange result = BoundedRangeOperation.unionIfIntersected(range1, range2); + + assertEquals(Bound.atLeast(1), result.getLowerBound()); + assertEquals(Bound.atMost(5), result.getUpperBound()); + } + @Test public void testEquals() { final Bound bound = new FiniteBound<>(1, BoundType.OPEN_UPPER_BOUND); diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/RangeTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/RangeTest.java index 0c9be907bf32c9a3165e26bd5cc9d50708090bed..be8f2e37a23d6921d1bd903fb726201514c70390 100644 --- a/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/RangeTest.java +++ b/hutool-core/src/test/java/cn/hutool/v7/core/lang/range/RangeTest.java @@ -22,13 +22,17 @@ import cn.hutool.v7.core.date.DateTime; import cn.hutool.v7.core.date.DateUtil; import cn.hutool.v7.core.text.StrUtil; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** * {@link Range} 单元测试 * @@ -36,6 +40,18 @@ import java.util.NoSuchElementException; */ public class RangeTest { + @Test + @DisplayName("测试不包含起始元素的迭代") + void testIteratorWithoutIncludeStart() { + Range range = new Range<>(1, 5, (current, end, index) -> current + 1, false, true); + List elements = new ArrayList<>(); + for (Integer i : range) { + elements.add(i); + } + + assertEquals(List.of(2, 3, 4, 5), elements); + } + @Test public void dateRangeTest() { final DateTime start = DateUtil.parse("2017-01-01"); @@ -50,9 +66,9 @@ public class RangeTest { final Iterator iterator = range.iterator(); Assertions.assertTrue(iterator.hasNext()); - Assertions.assertEquals(DateUtil.parse("2017-01-01"), iterator.next()); + assertEquals(DateUtil.parse("2017-01-01"), iterator.next()); Assertions.assertTrue(iterator.hasNext()); - Assertions.assertEquals(DateUtil.parse("2017-01-02"), iterator.next()); + assertEquals(DateUtil.parse("2017-01-02"), iterator.next()); Assertions.assertFalse(iterator.hasNext()); } @@ -75,11 +91,11 @@ public class RangeTest { final StringBuilder sb = new StringBuilder(); DateUtil.rangeConsume(start, end, DateField.DAY_OF_YEAR, a -> sb.append(DateTime.of(a).dayOfMonth()).append("#")); - Assertions.assertEquals("1#2#3#", sb.toString()); + assertEquals("1#2#3#", sb.toString()); final StringBuilder sb2 = new StringBuilder(); DateUtil.rangeConsume(null, null, DateField.DAY_OF_YEAR, a -> sb2.append(DateTime.of(a).dayOfMonth()).append("#")); - Assertions.assertEquals(StrUtil.EMPTY, sb2.toString()); + assertEquals(StrUtil.EMPTY, sb2.toString()); } @Test @@ -90,11 +106,11 @@ public class RangeTest { final DateRange range = DateUtil.range(start, end, DateField.MONTH); final Iterator iterator = range.iterator(); Assertions.assertTrue(iterator.hasNext()); - Assertions.assertEquals(DateUtil.parse("2021-01-31"), iterator.next()); + assertEquals(DateUtil.parse("2021-01-31"), iterator.next()); Assertions.assertTrue(iterator.hasNext()); - Assertions.assertEquals(DateUtil.parse("2021-02-28"), iterator.next()); + assertEquals(DateUtil.parse("2021-02-28"), iterator.next()); Assertions.assertTrue(iterator.hasNext()); - Assertions.assertEquals(DateUtil.parse("2021-03-31"), iterator.next()); + assertEquals(DateUtil.parse("2021-03-31"), iterator.next()); Assertions.assertFalse(iterator.hasNext()); } @@ -104,7 +120,7 @@ public class RangeTest { final Iterator iterator = range.iterator(); Assertions.assertTrue(iterator.hasNext()); - Assertions.assertEquals(Integer.valueOf(1), iterator.next()); + assertEquals(Integer.valueOf(1), iterator.next()); Assertions.assertFalse(iterator.hasNext()); } @@ -116,9 +132,9 @@ public class RangeTest { // 测试包含开始和结束情况下步进为1的情况 DateRange range = DateUtil.range(start, end, DateField.DAY_OF_YEAR); Iterator iterator = range.iterator(); - Assertions.assertEquals(iterator.next(), DateUtil.parse("2017-01-01")); - Assertions.assertEquals(iterator.next(), DateUtil.parse("2017-01-02")); - Assertions.assertEquals(iterator.next(), DateUtil.parse("2017-01-03")); + assertEquals(iterator.next(), DateUtil.parse("2017-01-01")); + assertEquals(iterator.next(), DateUtil.parse("2017-01-02")); + assertEquals(iterator.next(), DateUtil.parse("2017-01-03")); try { iterator.next(); Assertions.fail("已超过边界,下一个元素不应该存在!"); @@ -128,8 +144,8 @@ public class RangeTest { // 测试多步进的情况 range = new DateRange(start, end, DateField.DAY_OF_YEAR, 2); iterator = range.iterator(); - Assertions.assertEquals(DateUtil.parse("2017-01-01"), iterator.next()); - Assertions.assertEquals(DateUtil.parse("2017-01-03"), iterator.next()); + assertEquals(DateUtil.parse("2017-01-01"), iterator.next()); + assertEquals(DateUtil.parse("2017-01-03"), iterator.next()); } @Test @@ -140,9 +156,9 @@ public class RangeTest { // 测试不包含开始结束时间的情况 final DateRange range = new DateRange(start, end, DateField.DAY_OF_YEAR, 1, false, false); final Iterator iterator = range.iterator(); - Assertions.assertEquals(DateUtil.parse("2017-01-02"), iterator.next()); - Assertions.assertEquals(DateUtil.parse("2017-01-03"), iterator.next()); - Assertions.assertEquals(DateUtil.parse("2017-01-04"), iterator.next()); + assertEquals(DateUtil.parse("2017-01-02"), iterator.next()); + assertEquals(DateUtil.parse("2017-01-03"), iterator.next()); + assertEquals(DateUtil.parse("2017-01-04"), iterator.next()); try { iterator.next(); Assertions.fail("不包含结束时间情况下,下一个元素不应该存在!"); @@ -156,8 +172,8 @@ public class RangeTest { final Date end = DateUtil.parse("2017-01-31"); final List rangeToList = DateUtil.rangeToList(start, end, DateField.DAY_OF_YEAR); - Assertions.assertEquals(DateUtil.parse("2017-01-01"), rangeToList.get(0)); - Assertions.assertEquals(DateUtil.parse("2017-01-02"), rangeToList.get(1)); + assertEquals(DateUtil.parse("2017-01-01"), rangeToList.get(0)); + assertEquals(DateUtil.parse("2017-01-02"), rangeToList.get(1)); } @@ -173,8 +189,8 @@ public class RangeTest { final DateRange endRange = DateUtil.range(start1, end1, DateField.DAY_OF_YEAR); // 交集 final List dateTimes = DateUtil.rangeContains(startRange, endRange); - Assertions.assertEquals(1, dateTimes.size()); - Assertions.assertEquals(DateUtil.parse("2017-01-31"), dateTimes.get(0)); + assertEquals(1, dateTimes.size()); + assertEquals(DateUtil.parse("2017-01-31"), dateTimes.get(0)); } @Test @@ -190,8 +206,8 @@ public class RangeTest { // 差集 final List dateTimes1 = DateUtil.rangeNotContains(startRange, endRange); - Assertions.assertEquals(1, dateTimes1.size()); - Assertions.assertEquals(DateUtil.parse("2017-01-31"), dateTimes1.get(0)); + assertEquals(1, dateTimes1.size()); + assertEquals(DateUtil.parse("2017-01-31"), dateTimes1.get(0)); } } diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/lang/ref/PhantomObjTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/lang/ref/PhantomObjTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6e385273b5900cea12305eaecf718811e6ed966d --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/v7/core/lang/ref/PhantomObjTest.java @@ -0,0 +1,31 @@ +package cn.hutool.v7.core.lang.ref; + +import java.lang.ref.ReferenceQueue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class PhantomObjTest { + + private ReferenceQueue queue; + private String testObject; + private PhantomObj phantomObj; + + @BeforeEach + void setUp() { + queue = new ReferenceQueue<>(); + testObject = "test"; + phantomObj = new PhantomObj<>(testObject, queue); + } + + @Test + @DisplayName("测试 equals 方法与不同引用对象比较") + void testEqualsWithDifferentReferent() { + String differentObject = "different"; + PhantomObj anotherPhantomObj = new PhantomObj<>(differentObject, queue); + assertFalse(phantomObj.equals(anotherPhantomObj)); + } +}