add methods

This commit is contained in:
Looly 2022-03-31 02:09:12 +08:00
parent 0a9a178fbc
commit ae628d5a2c
9 changed files with 277 additions and 52 deletions

View File

@ -11,7 +11,7 @@ import java.util.NoSuchElementException;
* @author Looly * @author Looly
* @since 4.1.1 * @since 4.1.1
*/ */
public class ArrayIter<E> implements IterableIter<E>, Serializable { public class ArrayIter<E> implements IterableIter<E>, ResettableIter<E>, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
@ -126,6 +126,7 @@ public class ArrayIter<E> implements IterableIter<E>, Serializable {
/** /**
* 重置数组位置 * 重置数组位置
*/ */
@Override
public void reset() { public void reset() {
this.index = this.startIndex; this.index = this.startIndex;
} }

View File

@ -2212,17 +2212,8 @@ public class CollUtil {
final List<T> list = ((List<T>) collection); final List<T> list = ((List<T>) collection);
return list.get(index); return list.get(index);
} else { } else {
int i = 0; return IterUtil.get(collection.iterator(), index);
for (T t : collection) {
if (i > index) {
break;
} else if (i == index) {
return t;
}
i++;
}
} }
return null;
} }
/** /**
@ -2303,7 +2294,9 @@ public class CollUtil {
* @return 元素类型当列表为空或元素全部为null时返回null * @return 元素类型当列表为空或元素全部为null时返回null
* @see IterUtil#getElementType(Iterable) * @see IterUtil#getElementType(Iterable)
* @since 3.0.8 * @since 3.0.8
* @deprecated 请使用 {@link IterUtil#getElementType(Iterable)}
*/ */
@Deprecated
public static Class<?> getElementType(Iterable<?> iterable) { public static Class<?> getElementType(Iterable<?> iterable) {
return IterUtil.getElementType(iterable); return IterUtil.getElementType(iterable);
} }
@ -2315,7 +2308,9 @@ public class CollUtil {
* @return 元素类型当列表为空或元素全部为null时返回null * @return 元素类型当列表为空或元素全部为null时返回null
* @see IterUtil#getElementType(Iterator) * @see IterUtil#getElementType(Iterator)
* @since 3.0.8 * @since 3.0.8
* @deprecated 请使用 {@link IterUtil#getElementType(Iterator)}
*/ */
@Deprecated
public static Class<?> getElementType(Iterator<?> iterator) { public static Class<?> getElementType(Iterator<?> iterator) {
return IterUtil.getElementType(iterator); return IterUtil.getElementType(iterator);
} }

View File

@ -16,7 +16,6 @@ import java.util.List;
* <p> * <p>
* 需要注意的是在构造此对象时需要保证原子性原对象不被修改最好加锁构造此对象构造完毕后解锁 * 需要注意的是在构造此对象时需要保证原子性原对象不被修改最好加锁构造此对象构造完毕后解锁
* *
*
* @param <E> 元素类型 * @param <E> 元素类型
* @author Looly * @author Looly
* @since 3.0.7 * @since 3.0.7
@ -26,16 +25,24 @@ public class CopiedIter<E> implements IterableIter<E>, Serializable {
private final Iterator<E> listIterator; private final Iterator<E> listIterator;
public static <V> CopiedIter<V> copyOf(Iterator<V> iterator){ /**
* 根据已有{@link Iterator}返回新的{@code CopiedIter}
*
* @param iterator {@link Iterator}
* @param <E> 元素类型
* @return {@code CopiedIter}
*/
public static <E> CopiedIter<E> copyOf(Iterator<E> iterator) {
return new CopiedIter<>(iterator); return new CopiedIter<>(iterator);
} }
/** /**
* 构造 * 构造
*
* @param iterator 被复制的Iterator * @param iterator 被复制的Iterator
*/ */
public CopiedIter(Iterator<E> iterator) { public CopiedIter(Iterator<E> iterator) {
final List<E> eleList = CollUtil.newArrayList(iterator); final List<E> eleList = ListUtil.toList(iterator);
this.listIterator = eleList.iterator(); this.listIterator = eleList.iterator();
} }
@ -51,10 +58,11 @@ public class CopiedIter<E> implements IterableIter<E>, Serializable {
/** /**
* 此对象不支持移除元素 * 此对象不支持移除元素
*
* @throws UnsupportedOperationException 当调用此方法时始终抛出此异常 * @throws UnsupportedOperationException 当调用此方法时始终抛出此异常
*/ */
@Override @Override
public void remove() throws UnsupportedOperationException{ public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException("This is a read-only iterator."); throw new UnsupportedOperationException("This is a read-only iterator.");
} }
} }

View File

@ -8,12 +8,17 @@ import cn.hutool.core.lang.Matcher;
import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrJoiner; import cn.hutool.core.text.StrJoiner;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import com.sun.xml.internal.ws.util.xml.NodeListIterator;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -21,6 +26,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
/** /**
@ -511,11 +517,7 @@ public class IterUtil {
* @since 4.0.6 * @since 4.0.6
*/ */
public static <E> List<E> toList(Iterator<E> iter) { public static <E> List<E> toList(Iterator<E> iter) {
final List<E> list = new ArrayList<>(); return ListUtil.toList(iter);
while (iter.hasNext()) {
list.add(iter.next());
}
return list;
} }
/** /**
@ -543,17 +545,35 @@ public class IterUtil {
} }
/** /**
* 获取集合的第一个元素 * 遍历{@link Iterator}获取指定index位置的元素
*
* @param iterator {@link Iterator}
* @param index 位置
* @param <E> 元素类型
* @return 元素找不到元素返回{@code null}
* @since 5.8.0
*/
public static <E> E get(final Iterator<E> iterator, int index) throws IndexOutOfBoundsException {
Assert.isTrue(index >= 0, "[index] must be >= 0");
while (iterator.hasNext()) {
index--;
if (-1 == index) {
return iterator.next();
}
iterator.next();
}
return null;
}
/**
* 获取集合的第一个元素如果集合为空null或者空集合返回{@code null}
* *
* @param <T> 集合元素类型 * @param <T> 集合元素类型
* @param iterable {@link Iterable} * @param iterable {@link Iterable}
* @return 第一个元素 * @return 第一个元素为空返回{@code null}
*/ */
public static <T> T getFirst(Iterable<T> iterable) { public static <T> T getFirst(Iterable<T> iterable) {
if (null == iterable) { return getFirst(getIter(iterable));
return null;
}
return getFirst(iterable.iterator());
} }
/** /**
@ -579,10 +599,7 @@ public class IterUtil {
* @return 第一个元素 * @return 第一个元素
*/ */
public static <T> T getFirst(Iterator<T> iterator) { public static <T> T getFirst(Iterator<T> iterator) {
if (null != iterator && iterator.hasNext()) { return get(iterator, 0);
return iterator.next();
}
return null;
} }
/** /**
@ -627,29 +644,22 @@ public class IterUtil {
* @return 元素类型当列表为空或元素全部为null时返回null * @return 元素类型当列表为空或元素全部为null时返回null
*/ */
public static Class<?> getElementType(Iterable<?> iterable) { public static Class<?> getElementType(Iterable<?> iterable) {
if (null != iterable) { return getElementType(getIter(iterable));
final Iterator<?> iterator = iterable.iterator();
return getElementType(iterator);
}
return null;
} }
/** /**
* 获得{@link Iterator}对象的元素类型通过第一个非空元素判断<br> * 获得{@link Iterator}对象的元素类型通过第一个非空元素判断<br>
* 注意此方法至少会调用多次next方法 * 注意此方法至少会调用多次next方法
* *
* @param iterator {@link Iterator} * @param iterator {@link Iterator} {@code null}返回{@code null}
* @return 元素类型当列表为空或元素全部为null时返回null * @return 元素类型当列表为空或元素全部为{@code null}返回{@code null}
*/ */
public static Class<?> getElementType(Iterator<?> iterator) { public static Class<?> getElementType(Iterator<?> iterator) {
final Iterator<?> iter2 = new CopiedIter<>(iterator); if (null == iterator) {
while (iter2.hasNext()) { return null;
final Object t = iter2.next();
if (null != t) {
return t.getClass();
}
} }
return null; final Object ele = getFirstNoneNull(iterator);
return null == ele ? null : ele.getClass();
} }
/** /**
@ -751,9 +761,9 @@ public class IterUtil {
/** /**
* 获取一个新的 {@link FilterIter}用于过滤指定元素 * 获取一个新的 {@link FilterIter}用于过滤指定元素
* *
* @param iterator 被包装的 {@link Iterator} * @param iterator 被包装的 {@link Iterator}
* @param filter 过滤断言{@link Filter#accept(Object)}{@code true}时保留元素{@code false}抛弃元素 * @param filter 过滤断言{@link Filter#accept(Object)}{@code true}时保留元素{@code false}抛弃元素
* @param <E> 元素类型 * @param <E> 元素类型
* @return {@link FilterIter} * @return {@link FilterIter}
* @since 5.8.0 * @since 5.8.0
*/ */
@ -924,4 +934,124 @@ public class IterUtil {
} }
} }
} }
/**
* 遍历{@link Iterator}<br>
* 当consumer为{@code null}表示不处理但是依旧遍历{@link Iterator}
*
* @param iterator {@link Iterator}
* @param consumer 节点消费{@code null}表示不处理
* @param <E> 元素类型
* @since 5.8.0
*/
public static <E> void forEach(final Iterator<E> iterator, final Consumer<? super E> consumer) {
if (iterator != null) {
while (iterator.hasNext()) {
final E element = iterator.next();
if (null != consumer) {
consumer.accept(element);
}
}
}
}
/**
* 拼接 {@link Iterator}为字符串
*
* @param iterator {@link Iterator}
* @param <E> 元素类型
* @return 字符串
* @since 5.8.0
*/
public static <E> String toStr(final Iterator<E> iterator) {
return toStr(iterator, ObjectUtil::toString);
}
/**
* 拼接 {@link Iterator}为字符串
*
* @param iterator {@link Iterator}
* @param transFunc 元素转字符串函数
* @param <E> 元素类型
* @return 字符串
* @since 5.8.0
*/
public static <E> String toStr(final Iterator<E> iterator, final Function<? super E, String> transFunc) {
return toStr(iterator, transFunc, ", ", "[", "]");
}
/**
* 拼接 {@link Iterator}为字符串
*
* @param iterator {@link Iterator}
* @param transFunc 元素转字符串函数
* @param delimiter 分隔符
* @param prefix 前缀
* @param suffix 后缀
* @param <E> 元素类型
* @return 字符串
* @since 5.8.0
*/
public static <E> String toStr(final Iterator<E> iterator,
final Function<? super E, String> transFunc,
final String delimiter,
final String prefix,
final String suffix) {
final StrJoiner strJoiner = StrJoiner.of(delimiter, prefix, suffix);
strJoiner.append(iterator, transFunc);
return strJoiner.toString();
}
/**
* 从给定的对象中获取可能存在的{@link Iterator}规则如下
* <ul>
* <li>null - null</li>
* <li>Iterator - 直接返回</li>
* <li>Enumeration - {@link EnumerationIter}</li>
* <li>Collection - 调用{@link Collection#iterator()}</li>
* <li>Map - Entry的{@link Iterator}</li>
* <li>Dictionary - values (elements) enumeration returned as iterator</li>
* <li>array - {@link ArrayIter}</li>
* <li>NodeList - {@link NodeListIter}</li>
* <li>Node - 子节点</li>
* <li>object with iterator() public method通过反射访问</li>
* <li>object - 单对象的{@link ArrayIter}</li>
* </ul>
*
* @param obj 可以获取{@link Iterator}的对象
* @return {@link Iterator}如果提供对象为{@code null}返回{@code null}
*/
public static Iterator<?> getIter(final Object obj) {
if (obj == null) {
return null;
} else if (obj instanceof Iterator) {
return (Iterator<?>) obj;
} else if (obj instanceof Iterable) {
return ((Iterable<?>) obj).iterator();
} else if (ArrayUtil.isArray(obj)) {
return new ArrayIter<>(obj);
} else if (obj instanceof Enumeration) {
return new EnumerationIter<>((Enumeration<?>) obj);
} else if (obj instanceof Map) {
return ((Map<?, ?>) obj).entrySet().iterator();
} else if (obj instanceof NodeList) {
return new NodeListIterator((NodeList) obj);
} else if (obj instanceof Node) {
// 遍历子节点
return new NodeListIterator(((Node) obj).getChildNodes());
} else if (obj instanceof Dictionary) {
return new EnumerationIter<>(((Dictionary<?, ?>) obj).elements());
}
// 反射获取
try {
final Object iterator = ReflectUtil.invoke(obj, "iterator");
if (iterator instanceof Iterator) {
return (Iterator<?>) iterator;
}
} catch (final RuntimeException ignore) {
// ignore
}
return new ArrayIter<>(new Object[]{obj});
}
} }

View File

@ -10,6 +10,7 @@ import java.util.Iterator;
* @since 5.7.14 * @since 5.7.14
*/ */
public interface IterableIter<T> extends Iterable<T>, Iterator<T> { public interface IterableIter<T> extends Iterable<T>, Iterator<T> {
@Override @Override
default Iterator<T> iterator() { default Iterator<T> iterator() {
return this; return this;

View File

@ -0,0 +1,63 @@
package cn.hutool.core.collection;
import cn.hutool.core.lang.Assert;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* 包装 {@link NodeList} {@link Iterator}
* <p>
* iterator 不支持 {@link #remove()} 方法
*
* @author apache commons,looly
* @see NodeList
* @since 5.8.0
*/
public class NodeListIter implements ResettableIter<Node> {
private final NodeList nodeList;
/**
* 当前位置索引
*/
private int index = 0;
/**
* 构造, 根据给定{@link NodeList} 创建{@code NodeListIterator}
*
* @param nodeList {@link NodeList}非空
*/
public NodeListIter(final NodeList nodeList) {
this.nodeList = Assert.notNull(nodeList, "NodeList must not be null.");
}
@Override
public boolean hasNext() {
return nodeList != null && index < nodeList.getLength();
}
@Override
public Node next() {
if (nodeList != null && index < nodeList.getLength()) {
return nodeList.item(index++);
}
throw new NoSuchElementException("underlying nodeList has no more elements");
}
/**
* Throws {@link UnsupportedOperationException}.
*
* @throws UnsupportedOperationException always
*/
@Override
public void remove() {
throw new UnsupportedOperationException("remove() method not supported for a NodeListIterator.");
}
@Override
public void reset() {
this.index = 0;
}
}

View File

@ -0,0 +1,18 @@
package cn.hutool.core.collection;
import java.util.Iterator;
/**
* 支持重置的{@link Iterator} 接口<br>
* 通过实现{@link #reset()}重置此{@link Iterator}后可实现复用重新遍历
*
* @param <E> 元素类型
* @since 5.8.0
*/
public interface ResettableIter<E> extends Iterator<E> {
/**
* 重置重置后可重新遍历
*/
void reset();
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.ArrayIter;
import cn.hutool.core.collection.IterUtil; import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import java.io.IOException; import java.io.IOException;
@ -211,7 +212,7 @@ public class StrJoiner implements Appendable, Serializable {
} else if (obj instanceof Iterable) { } else if (obj instanceof Iterable) {
append(((Iterable<?>) obj).iterator()); append(((Iterable<?>) obj).iterator());
} else { } else {
append(String.valueOf(obj)); append(ObjectUtil.toString(obj));
} }
return this; return this;
} }
@ -261,24 +262,24 @@ public class StrJoiner implements Appendable, Serializable {
/** /**
* 追加{@link Iterator}中的元素到拼接器中 * 追加{@link Iterator}中的元素到拼接器中
* *
* @param <T> 元素类型 * @param <E> 元素类型
* @param iterable 元素列表 * @param iterable 元素列表
* @param toStrFunc 元素对象转换为字符串的函数 * @param toStrFunc 元素对象转换为字符串的函数
* @return this * @return this
*/ */
public <T> StrJoiner append(Iterable<T> iterable, Function<T, ? extends CharSequence> toStrFunc) { public <E> StrJoiner append(Iterable<E> iterable, Function<? super E, ? extends CharSequence> toStrFunc) {
return append(IterUtil.getIter(iterable), toStrFunc); return append(IterUtil.getIter(iterable), toStrFunc);
} }
/** /**
* 追加{@link Iterator}中的元素到拼接器中 * 追加{@link Iterator}中的元素到拼接器中
* *
* @param <T> 元素类型 * @param <E> 元素类型
* @param iterator 元素列表 * @param iterator 元素列表
* @param toStrFunc 元素对象转换为字符串的函数 * @param toStrFunc 元素对象转换为字符串的函数
* @return this * @return this
*/ */
public <T> StrJoiner append(Iterator<T> iterator, Function<T, ? extends CharSequence> toStrFunc) { public <E> StrJoiner append(Iterator<E> iterator, Function<? super E, ? extends CharSequence> toStrFunc) {
if (null != iterator) { if (null != iterator) {
while (iterator.hasNext()) { while (iterator.hasNext()) {
append(toStrFunc.apply(iterator.next())); append(toStrFunc.apply(iterator.next()));

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -136,4 +137,11 @@ public class IterUtilTest {
Assert.assertEquals(1, filtered.size()); Assert.assertEquals(1, filtered.size());
Assert.assertEquals("3", filtered.get(0)); Assert.assertEquals("3", filtered.get(0));
} }
@Test
public void getTest() {
HashSet<String> set = CollUtil.set(true, "A", "B", "C", "D");
String str = IterUtil.get(set.iterator(), 2);
Assert.assertEquals("C", str);
}
} }