mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
fix Range
This commit is contained in:
parent
3ca4063ea5
commit
721fd16f4d
@ -52,7 +52,6 @@ public class DateRange extends Range<DateTime> {
|
||||
if (dt.isAfter(end1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return dt;
|
||||
}, isIncludeStart, isIncludeEnd);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
* 范围生成器。根据给定的初始值、结束值和步进生成一个步进列表生成器<br>
|
||||
* 由于用户自行实现{@link Steper}来定义步进,因此Range本身无法判定边界(是否达到end),需在step实现边界判定逻辑。
|
||||
* 由于用户自行实现{@link Stepper}来定义步进,因此Range本身无法判定边界(是否达到end),需在step实现边界判定逻辑。
|
||||
*
|
||||
* <p>
|
||||
* 此类使用{@link ReentrantReadWriteLock}保证线程安全
|
||||
@ -35,10 +35,6 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
||||
* 结束对象
|
||||
*/
|
||||
private final T end;
|
||||
/**
|
||||
* 当前对象
|
||||
*/
|
||||
private T current;
|
||||
/**
|
||||
* 下一个对象
|
||||
*/
|
||||
@ -46,7 +42,7 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
||||
/**
|
||||
* 步进
|
||||
*/
|
||||
private final Steper<T> steper;
|
||||
private final Stepper<T> stepper;
|
||||
/**
|
||||
* 索引
|
||||
*/
|
||||
@ -58,27 +54,27 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
||||
/**
|
||||
* 是否包含最后一个元素
|
||||
*/
|
||||
private boolean includeEnd;
|
||||
private final boolean includeEnd;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param start 起始对象(包括)
|
||||
* @param steper 步进
|
||||
* @param start 起始对象(包括)
|
||||
* @param stepper 步进
|
||||
*/
|
||||
public Range(T start, Steper<T> steper) {
|
||||
this(start, null, steper);
|
||||
public Range(T start, Stepper<T> stepper) {
|
||||
this(start, null, stepper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param start 起始对象(包含)
|
||||
* @param end 结束对象(包含)
|
||||
* @param steper 步进
|
||||
* @param start 起始对象(包含)
|
||||
* @param end 结束对象(包含)
|
||||
* @param stepper 步进
|
||||
*/
|
||||
public Range(T start, T end, Steper<T> steper) {
|
||||
this(start, end, steper, true, true);
|
||||
public Range(T start, T end, Stepper<T> stepper) {
|
||||
this(start, end, stepper, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,23 +82,22 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
||||
*
|
||||
* @param start 起始对象
|
||||
* @param end 结束对象
|
||||
* @param steper 步进
|
||||
* @param stepper 步进
|
||||
* @param isIncludeStart 是否包含第一个元素
|
||||
* @param isIncludeEnd 是否包含最后一个元素
|
||||
*/
|
||||
public Range(T start, T end, Steper<T> steper, boolean isIncludeStart, boolean isIncludeEnd) {
|
||||
public Range(T start, T end, Stepper<T> stepper, boolean isIncludeStart, boolean isIncludeEnd) {
|
||||
Assert.notNull(start, "First element must be not null!");
|
||||
this.start = start;
|
||||
this.current = start;
|
||||
this.end = end;
|
||||
this.steper = steper;
|
||||
this.next = safeStep(this.current);
|
||||
this.stepper = stepper;
|
||||
this.next = safeStep(this.start);
|
||||
this.includeStart = isIncludeStart;
|
||||
includeEnd = true;
|
||||
this.includeEnd = isIncludeEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用锁,调用此方法后不在 使用锁保护
|
||||
* 禁用锁,调用此方法后不再使用锁保护
|
||||
*
|
||||
* @return this
|
||||
* @since 4.3.1
|
||||
@ -147,30 +142,38 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
||||
* 获取下一个元素,并将下下个元素准备好
|
||||
*/
|
||||
private T nextUncheck() {
|
||||
if (0 != this.index || false == this.includeStart) {
|
||||
// 非第一个元素或不包含第一个元素增加步进
|
||||
this.current = this.next;
|
||||
if (null != this.current) {
|
||||
this.next = safeStep(this.next);
|
||||
T current;
|
||||
if(0 == this.index){
|
||||
current = start;
|
||||
if(false == this.includeStart){
|
||||
// 获取下一组元素
|
||||
index ++;
|
||||
return nextUncheck();
|
||||
}
|
||||
} else {
|
||||
current = next;
|
||||
this.next = safeStep(this.next);
|
||||
}
|
||||
|
||||
index++;
|
||||
return this.current;
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* 不抛异常的获取下一步进的元素,如果获取失败返回{@code null}
|
||||
*
|
||||
* @param base 上一个元素
|
||||
* @param base 上一个元素
|
||||
* @return 下一步进
|
||||
*/
|
||||
private T safeStep(T base) {
|
||||
final int index = this.index;
|
||||
T next = null;
|
||||
try {
|
||||
next = steper.step(base, this.end, this.index);
|
||||
next = stepper.step(base, this.end, index);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
@ -192,8 +195,8 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
||||
public Range<T> reset() {
|
||||
lock.lock();
|
||||
try {
|
||||
this.current = this.start;
|
||||
this.index = 0;
|
||||
this.next = safeStep(this.start);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@ -213,7 +216,8 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
||||
* @param <T> 需要增加步进的对象
|
||||
* @author Looly
|
||||
*/
|
||||
public interface Steper<T> {
|
||||
@FunctionalInterface
|
||||
public interface Stepper<T> {
|
||||
/**
|
||||
* 增加步进<br>
|
||||
* 增加步进后的返回值如果为{@code null}则表示步进结束<br>
|
||||
|
@ -19,7 +19,6 @@ import java.util.Date;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@ -681,47 +680,6 @@ public class DateUtilTest {
|
||||
Assert.assertEquals(Week.WEDNESDAY, week);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rangeTest() {
|
||||
DateTime start = DateUtil.parse("2017-01-01");
|
||||
DateTime end = DateUtil.parse("2017-01-03");
|
||||
|
||||
// 测试包含开始和结束情况下步进为1的情况
|
||||
DateRange range = DateUtil.range(start, end, DateField.DAY_OF_YEAR);
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-01"));
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-02"));
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-03"));
|
||||
try {
|
||||
range.next();
|
||||
Assert.fail("已超过边界,下一个元素不应该存在!");
|
||||
} catch (NoSuchElementException ignored) {
|
||||
}
|
||||
|
||||
// 测试多步进的情况
|
||||
range = new DateRange(start, end, DateField.DAY_OF_YEAR, 2);
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-01"));
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-03"));
|
||||
|
||||
// 测试不包含开始结束时间的情况
|
||||
range = new DateRange(start, end, DateField.DAY_OF_YEAR, 1, false, false);
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-02"));
|
||||
try {
|
||||
range.next();
|
||||
Assert.fail("不包含结束时间情况下,下一个元素不应该存在!");
|
||||
} catch (NoSuchElementException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rangeToListTest() {
|
||||
DateTime start = DateUtil.parse("2017-01-01");
|
||||
DateTime end = DateUtil.parse("2017-01-31");
|
||||
|
||||
List<DateTime> rangeToList = DateUtil.rangeToList(start, end, DateField.DAY_OF_YEAR);
|
||||
Assert.assertEquals(rangeToList.get(0), DateUtil.parse("2017-01-01"));
|
||||
Assert.assertEquals(rangeToList.get(1), DateUtil.parse("2017-01-02"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTest() {
|
||||
Date date1 = DateUtil.parse("2021-04-13 23:59:59.999");
|
||||
|
@ -7,6 +7,9 @@ import cn.hutool.core.date.DateUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* {@link Range} 单元测试
|
||||
* @author Looly
|
||||
@ -57,4 +60,53 @@ public class RangeTest {
|
||||
Assert.assertEquals(Integer.valueOf(1), range.next());
|
||||
Assert.assertFalse(range.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rangeByStepTest() {
|
||||
DateTime start = DateUtil.parse("2017-01-01");
|
||||
DateTime end = DateUtil.parse("2017-01-03");
|
||||
|
||||
// 测试包含开始和结束情况下步进为1的情况
|
||||
DateRange range = DateUtil.range(start, end, DateField.DAY_OF_YEAR);
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-01"));
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-02"));
|
||||
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-03"));
|
||||
try {
|
||||
range.next();
|
||||
Assert.fail("已超过边界,下一个元素不应该存在!");
|
||||
} catch (NoSuchElementException ignored) {
|
||||
}
|
||||
|
||||
// 测试多步进的情况
|
||||
range = new DateRange(start, end, DateField.DAY_OF_YEAR, 2);
|
||||
Assert.assertEquals(DateUtil.parse("2017-01-01"), range.next());
|
||||
Assert.assertEquals(DateUtil.parse("2017-01-03"), range.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rangeDayOfYearTest(){
|
||||
DateTime start = DateUtil.parse("2017-01-01");
|
||||
DateTime end = DateUtil.parse("2017-01-05");
|
||||
|
||||
// 测试不包含开始结束时间的情况
|
||||
DateRange range = new DateRange(start, end, DateField.DAY_OF_YEAR, 1, false, false);
|
||||
Assert.assertEquals(DateUtil.parse("2017-01-02"), range.next());
|
||||
Assert.assertEquals(DateUtil.parse("2017-01-03"), range.next());
|
||||
Assert.assertEquals(DateUtil.parse("2017-01-04"), range.next());
|
||||
try {
|
||||
range.next();
|
||||
Assert.fail("不包含结束时间情况下,下一个元素不应该存在!");
|
||||
} catch (NoSuchElementException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rangeToListTest() {
|
||||
DateTime start = DateUtil.parse("2017-01-01");
|
||||
DateTime end = DateUtil.parse("2017-01-31");
|
||||
|
||||
List<DateTime> rangeToList = DateUtil.rangeToList(start, end, DateField.DAY_OF_YEAR);
|
||||
Assert.assertEquals(DateUtil.parse("2017-01-01"), rangeToList.get(0));
|
||||
Assert.assertEquals(DateUtil.parse("2017-01-02"), rangeToList.get(1));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user