diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java index 52d977d00..7002f2117 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java @@ -18,9 +18,9 @@ package org.dromara.hutool.core.date; import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.comparator.CompareUtil; +import org.dromara.hutool.core.date.format.DateFormatManager; import org.dromara.hutool.core.date.format.DatePrinter; import org.dromara.hutool.core.date.format.FastDateFormat; -import org.dromara.hutool.core.date.format.DateFormatManager; import org.dromara.hutool.core.date.format.parser.PositionDateParser; import org.dromara.hutool.core.date.format.parser.RegisterDateParser; import org.dromara.hutool.core.lang.Assert; diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/range/Range.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/range/Range.java index cfa64c089..df38e5d04 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/lang/range/Range.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/range/Range.java @@ -17,13 +17,10 @@ package org.dromara.hutool.core.lang.range; import org.dromara.hutool.core.lang.Assert; -import org.dromara.hutool.core.thread.lock.NoLock; import java.io.Serializable; import java.util.Iterator; import java.util.NoSuchElementException; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** @@ -37,13 +34,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * @param 生成范围对象的类型 * @author Looly */ -public class Range implements Iterable, Iterator, Serializable { +public class Range implements Iterable, Serializable { private static final long serialVersionUID = 1L; - /** - * 锁保证线程安全 - */ - private Lock lock = new ReentrantLock(); /** * 起始对象 */ @@ -52,18 +45,11 @@ public class Range implements Iterable, Iterator, Serializable { * 结束对象 */ private final T end; - /** - * 下一个对象 - */ - private T next; + /** * 步进 */ private final Stepper stepper; - /** - * 索引 - */ - private int index = 0; /** * 是否包含第一个元素 */ @@ -108,116 +94,86 @@ public class Range implements Iterable, Iterator, Serializable { this.start = start; this.end = end; this.stepper = stepper; - this.next = safeStep(this.start); this.includeStart = isIncludeStart; this.includeEnd = isIncludeEnd; } - /** - * 禁用锁,调用此方法后不再使用锁保护 - * - * @return this - * @since 4.3.1 - */ - public Range disableLock() { - this.lock = new NoLock(); - return this; - } - - @Override - public boolean hasNext() { - lock.lock(); - try { - if (0 == this.index && this.includeStart) { - return true; - } - if (null == this.next) { - return false; - } else if (!includeEnd && this.next.equals(this.end)) { - return false; - } - } finally { - lock.unlock(); - } - return true; - } - - @Override - public T next() { - lock.lock(); - try { - if (!this.hasNext()) { - throw new NoSuchElementException("Has no next range!"); - } - return nextUncheck(); - } finally { - lock.unlock(); - } - } - - /** - * 获取下一个元素,并将下下个元素准备好 - */ - private T nextUncheck() { - final T current; - if(0 == this.index){ - current = start; - if(!this.includeStart){ - // 获取下一组元素 - index ++; - return nextUncheck(); - } - } else { - current = next; - this.next = safeStep(this.next); - } - - index++; - return current; - } - - /** - * 不抛异常的获取下一步进的元素,如果获取失败返回{@code null} - * - * @param base 上一个元素 - * @return 下一步进 - */ - private T safeStep(final T base) { - final int index = this.index; - T next = null; - try { - next = stepper.step(base, this.end, index); - } catch (final Exception e) { - // ignore - } - - return next; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Can not remove ranged element!"); - } - @Override public Iterator iterator() { - return this; - } + return new Iterator(){ + /** + * 下一个对象 + */ + private T next = safeStep(start); + /** + * 索引 + */ + private int index = 0; - /** - * 重置Range - * - * @return this - */ - public Range reset() { - lock.lock(); - try { - this.index = 0; - this.next = safeStep(this.start); - } finally { - lock.unlock(); - } - return this; + @Override + public boolean hasNext() { + if (0 == this.index && includeStart) { + return true; + } + if (null == this.next) { + return false; + } else { + return includeEnd || !this.next.equals(end); + } + } + + @Override + public T next() { + if (!this.hasNext()) { + throw new NoSuchElementException("Has no next range!"); + } + return nextUncheck(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Can not remove ranged element!"); + } + + /** + * 获取下一个元素,并将下下个元素准备好 + */ + private T nextUncheck() { + final T current; + if(0 == this.index){ + current = start; + if(!includeStart){ + // 获取下一组元素 + index ++; + return nextUncheck(); + } + } else { + current = next; + this.next = safeStep(this.next); + } + + index++; + return current; + } + + /** + * 不抛异常的获取下一步进的元素,如果获取失败返回{@code null} + * + * @param base 上一个元素 + * @return 下一步进 + */ + private T safeStep(final T base) { + final int index = this.index; + T next = null; + try { + next = stepper.step(base, end, index); + } catch (final Exception e) { + // ignore + } + + return next; + } + }; } /** @@ -247,4 +203,9 @@ public class Range implements Iterable, Iterator, Serializable { */ T step(T current, T end, int index); } + + @Override + public String toString() { + return "Range [start=" + start + ", end=" + end + "]"; + } } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/data/Issue3081Test.java b/hutool-core/src/test/java/org/dromara/hutool/core/data/Issue3081Test.java index 06eff943d..88eefe516 100755 --- a/hutool-core/src/test/java/org/dromara/hutool/core/data/Issue3081Test.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/data/Issue3081Test.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Date; +import java.util.Iterator; import java.util.List; public class Issue3081Test { @@ -35,10 +36,10 @@ public class Issue3081Test { final Date end = DateUtil.parse("2023-04-25 00:00:00"); final DateRange dateTimes = new DateRange(start, end, DateField.DAY_OF_MONTH, 30, true, true); - + final Iterator iterator = dateTimes.iterator(); final List dateTimeList = new ArrayList<>(); - while (dateTimes.hasNext()) { - dateTimeList.add(dateTimes.next()); + while (iterator.hasNext()) { + dateTimeList.add(iterator.next()); } Assertions.assertEquals(4, dateTimeList.size()); diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/IssueIB8OFSTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/IssueIB8OFSTest.java new file mode 100644 index 000000000..05f55d222 --- /dev/null +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/IssueIB8OFSTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Hutool Team and hutool.cn + * + * 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 + * + * http://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 org.dromara.hutool.core.date; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +public class IssueIB8OFSTest { + @Test + void rangeTest() { + DateRange startRange = DateUtil.range( + DateUtil.parse("2017-01-01"), + DateUtil.parse("2017-01-31"), DateField.DAY_OF_YEAR); + DateRange endRange = DateUtil.range( + DateUtil.parse("2017-01-31"), + DateUtil.parse("2017-02-02"), DateField.DAY_OF_YEAR); + + List dateTimes = DateUtil.rangeContains(startRange, endRange); + System.out.println("交集: "); + dateTimes.forEach(System.out::println); + + List dateNotTimes = DateUtil.rangeNotContains(startRange, endRange); + System.out.println("差集: "); + dateNotTimes.forEach(System.out::println); + } +} diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/range/RangeTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/lang/range/RangeTest.java index 16fd4a4bc..2f6542174 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/range/RangeTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/lang/range/RangeTest.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; @@ -47,11 +48,12 @@ public class RangeTest { return current.offsetNew(DateField.DAY_OF_YEAR, 1); }); - Assertions.assertTrue(range.hasNext()); - Assertions.assertEquals(DateUtil.parse("2017-01-01"), range.next()); - Assertions.assertTrue(range.hasNext()); - Assertions.assertEquals(DateUtil.parse("2017-01-02"), range.next()); - Assertions.assertFalse(range.hasNext()); + final Iterator iterator = range.iterator(); + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(DateUtil.parse("2017-01-01"), iterator.next()); + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(DateUtil.parse("2017-01-02"), iterator.next()); + Assertions.assertFalse(iterator.hasNext()); } @Test @@ -86,23 +88,24 @@ public class RangeTest { final Date end = DateUtil.parse("2021-03-31"); final DateRange range = DateUtil.range(start, end, DateField.MONTH); - - Assertions.assertTrue(range.hasNext()); - Assertions.assertEquals(DateUtil.parse("2021-01-31"), range.next()); - Assertions.assertTrue(range.hasNext()); - Assertions.assertEquals(DateUtil.parse("2021-02-28"), range.next()); - Assertions.assertTrue(range.hasNext()); - Assertions.assertEquals(DateUtil.parse("2021-03-31"), range.next()); - Assertions.assertFalse(range.hasNext()); + final Iterator iterator = range.iterator(); + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(DateUtil.parse("2021-01-31"), iterator.next()); + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(DateUtil.parse("2021-02-28"), iterator.next()); + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(DateUtil.parse("2021-03-31"), iterator.next()); + Assertions.assertFalse(iterator.hasNext()); } @Test public void intRangeTest() { final Range range = new Range<>(1, 1, (current, end, index) -> current >= end ? null : current + 10); + final Iterator iterator = range.iterator(); - Assertions.assertTrue(range.hasNext()); - Assertions.assertEquals(Integer.valueOf(1), range.next()); - Assertions.assertFalse(range.hasNext()); + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(Integer.valueOf(1), iterator.next()); + Assertions.assertFalse(iterator.hasNext()); } @Test @@ -112,19 +115,21 @@ public class RangeTest { // 测试包含开始和结束情况下步进为1的情况 DateRange range = DateUtil.range(start, end, DateField.DAY_OF_YEAR); - Assertions.assertEquals(range.next(), DateUtil.parse("2017-01-01")); - Assertions.assertEquals(range.next(), DateUtil.parse("2017-01-02")); - Assertions.assertEquals(range.next(), DateUtil.parse("2017-01-03")); + 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")); try { - range.next(); + iterator.next(); Assertions.fail("已超过边界,下一个元素不应该存在!"); } catch (final NoSuchElementException ignored) { } // 测试多步进的情况 range = new DateRange(start, end, DateField.DAY_OF_YEAR, 2); - Assertions.assertEquals(DateUtil.parse("2017-01-01"), range.next()); - Assertions.assertEquals(DateUtil.parse("2017-01-03"), range.next()); + iterator = range.iterator(); + Assertions.assertEquals(DateUtil.parse("2017-01-01"), iterator.next()); + Assertions.assertEquals(DateUtil.parse("2017-01-03"), iterator.next()); } @Test @@ -134,11 +139,12 @@ public class RangeTest { // 测试不包含开始结束时间的情况 final DateRange range = new DateRange(start, end, DateField.DAY_OF_YEAR, 1, false, false); - Assertions.assertEquals(DateUtil.parse("2017-01-02"), range.next()); - Assertions.assertEquals(DateUtil.parse("2017-01-03"), range.next()); - Assertions.assertEquals(DateUtil.parse("2017-01-04"), range.next()); + 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()); try { - range.next(); + iterator.next(); Assertions.fail("不包含结束时间情况下,下一个元素不应该存在!"); } catch (final NoSuchElementException ignored) { }