diff --git a/CHANGELOG.md b/CHANGELOG.md index 91653efa1..ccccfb9d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.0.M2 (2022-03-30) +# 5.8.0.M2 (2022-03-31) ### ❌不兼容特性 * 【extra 】 【可能兼容问题】BeanCopierCache的key结构变更 @@ -10,6 +10,7 @@ ### 🐣新特性 * 【core 】 MapUtil增加entry、ofEntries方法 * 【core 】 ZipWriter增加add方法重载 +* 【core 】 IterUtil增加filtered,增加FilterIter(issue#2228) ### 🐞Bug修复 * 【core 】 IdcardUtil#getCityCodeByIdCard位数问题(issue#2224@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/FilterIter.java b/hutool-core/src/main/java/cn/hutool/core/collection/FilterIter.java new file mode 100644 index 000000000..9c5ae2201 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/collection/FilterIter.java @@ -0,0 +1,96 @@ +package cn.hutool.core.collection; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Filter; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * 包装 {@link Iterator}并根据{@link Filter}定义,过滤元素输出
+ * 类实现来自Apache Commons Collection + * + * @author apache commons, looly + * @since 5.8.0 + */ +public class FilterIter implements Iterator { + + private final Iterator iterator; + private final Filter filter; + + /** + * 下一个元素 + */ + private E nextObject; + /** + * 标记下一个元素是否被计算 + */ + private boolean nextObjectSet = false; + + /** + * 构造 + * + * @param iterator 被包装的{@link Iterator} + * @param filter 过滤函数,{@code null}表示不过滤 + */ + public FilterIter(final Iterator iterator, final Filter filter) { + this.iterator = Assert.notNull(iterator); + this.filter = filter; + } + + @Override + public boolean hasNext() { + return nextObjectSet || setNextObject(); + } + + @Override + public E next() { + if (false == nextObjectSet && false == setNextObject()) { + throw new NoSuchElementException(); + } + nextObjectSet = false; + return nextObject; + } + + @Override + public void remove() { + if (nextObjectSet) { + throw new IllegalStateException("remove() cannot be called"); + } + iterator.remove(); + } + + /** + * 获取被包装的{@link Iterator} + * + * @return {@link Iterator} + */ + public Iterator getIterator() { + return iterator; + } + + /** + * 获取过滤函数 + * + * @return 过滤函数,可能为{@code null} + */ + public Filter getFilter() { + return filter; + } + + /** + * 设置下一个元素,如果存在返回{@code true},否则{@code false} + */ + private boolean setNextObject() { + while (iterator.hasNext()) { + final E object = iterator.next(); + if (null != filter && filter.accept(object)) { + nextObject = object; + nextObjectSet = true; + return true; + } + } + return false; + } + +} diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/IterUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/IterUtil.java index 57067264e..ddcafe36b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/IterUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/IterUtil.java @@ -745,17 +745,20 @@ public class IterUtil { * @since 5.7.22 */ public static List filterToList(Iterator iter, Filter filter) { - final List result = new ArrayList<>(); - if (null != iter) { - E ele; - while (iter.hasNext()) { - ele = iter.next(); - if (null == filter || filter.accept(ele)) { - result.add(ele); - } - } - } - return result; + return toList(filtered(iter, filter)); + } + + /** + * 获取一个新的 {@link FilterIter},用于过滤指定元素 + * + * @param iterator 被包装的 {@link Iterator} + * @param filter 过滤断言,当{@link Filter#accept(Object)}为{@code true}时保留元素,{@code false}抛弃元素 + * @param 元素类型 + * @return {@link FilterIter} + * @since 5.8.0 + */ + public static FilterIter filtered(final Iterator iterator, final Filter filter) { + return new FilterIter<>(iterator, filter); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/TransIter.java b/hutool-core/src/main/java/cn/hutool/core/collection/TransIter.java index 058a61d8b..116fd697a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/TransIter.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/TransIter.java @@ -24,7 +24,7 @@ public class TransIter implements Iterator { * @param backingIterator 源{@link Iterator} * @param func 转换函数 */ - public TransIter(Iterator backingIterator, Function func) { + public TransIter(final Iterator backingIterator, final Function func) { this.backingIterator = Assert.notNull(backingIterator); this.func = Assert.notNull(func); } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java index a0f9c7991..6e74468ba 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java @@ -103,4 +103,37 @@ public class IterUtilTest { private String carNumber; private String carName; } + + @Test + public void filterTest(){ + List obj2 = ListUtil.toList("3"); + List obj = ListUtil.toList("1", "3"); + + IterUtil.filter(obj.iterator(), obj2::contains); + + Assert.assertEquals(1, obj.size()); + Assert.assertEquals("3", obj.get(0)); + } + + @Test + public void filteredTest(){ + List obj2 = ListUtil.toList("3"); + List obj = ListUtil.toList("1", "3"); + + final FilterIter filtered = IterUtil.filtered(obj.iterator(), obj2::contains); + + Assert.assertEquals("3", filtered.next()); + Assert.assertFalse(filtered.hasNext()); + } + + @Test + public void filterToListTest(){ + List obj2 = ListUtil.toList("3"); + List obj = ListUtil.toList("1", "3"); + + final List filtered = IterUtil.filterToList(obj.iterator(), obj2::contains); + + Assert.assertEquals(1, filtered.size()); + Assert.assertEquals("3", filtered.get(0)); + } }