java集合拆包_拆行解码 Java 集合源码之迭代器

迭代器

还有一个接口 Iterator,每个集合类内部通过实现该接口,实现集合元素的遍历。将遍历序列的操作与序列底层的结构分离。

该对象必须依赖于具体容器,因为每一个容器的数据结构不同;

所以迭代器对象是在容器中进行实现的(内部类)。

迭代的时候只能进行删除(可选操作)。

for(Iterator it = Collection.iterator(); it.hasNext();){

E e=it.next();

it.remove();

}

复制代码

ps:1.2 之前是通过 Enumeration 接口实现遍历。

不是快速失败的!!

支持的集合较少,Hashtable 的键、值集合,Vector。

Iterator 允许遍历期间删除元素,方法命名更加友好。

foreach 与 迭代器

(1)foreach主要是针对数组或任何实现 Iterable 接口的类。

public interface Iterable{

Iterator iterator();

default void forEach(Consumer super T> action){

Objects.requireNonNull(action);

for (T t : this) {

action.accept(t);

}

}

/** * 返回一个可能并行的可拆分迭代器。 * 是基于原数据源(集合、数组、IO 流)的可拆分迭代器 * 虽然可以在并行流程中使用,但是并不是线程安全,尤其是拆分的过程。 * 建议在单线程的串行线程中使用,比如基于分治的任务分解过程。 */

default Spliterator spliterator(){

return Spliterators.spliteratorUnknownSize(iterator(), 0);

}

}

复制代码

(2)集合进行 foreach 循环时,会默认调用重写的 iterator 方法,得到实现 iterable 的迭代器对象 Iterator,从而进行遍历。(实际是一种语法糖)

for (Integer e : list) {

// do some thing

}

=>

object = list.iterator();

while (object.hasNext()) {

Integer e = object.next());

}

复制代码

(3)集合可以写一个方法,返回一个实现了 Iterable 接口的 Iterator 类,进行不同方式的迭代。

注意:数组直接使用 foreach 进行遍历即可。不能够将数组转化为 Iterable 接口对象进行遍历,只能人为使用 Arrays.asList() 转化为 ArrayList 对象,然后默认调用 Iterator 方法进行遍历。

快速失败(fail fast)

集合在使用迭代器在遍历过程中,不能使用集合的 remove() 方法进行增删(修改可以),否则抛出ConcurrentModificationException。

只能使用迭代器的 remove 方法,方法内部对集合进行同步删除操作。

原理:将计数器与迭代器关联起来。在遍历每一个元素的时候都会检查一遍,返回迭代器时记录的expectedModCount 与现在容器的 ModCount 是否相等。(modCount 的含义是记录该容器被修改的次数,包括但不限于更改容器大小或其他可能干扰到迭代器的操作。)

如果使用容器的api进行操作,将无法同时更新两个变量的值,会导致失败。而迭代器的删除会同时维护索引表的内容,保证一致性。

快速失败并不是严谨保证不同步下的并发安全性,应该被用于检查bug。

**** 可拆分迭代器

public interface Spliterator{

// 一个数据源的Spliterator允许有多个特征,定义的特征通过 或运算 得到一个数据源的特征 characteristics()。

/** * 标识数据源的元素是有序的 */

public static final int ORDERED = 0x00000010;

/** * 标识数据源的元素是不重复的。比如基于 Set的 */

public static final int DISTINCT = 0x00000001;

/** * 数据源的元素是按照一定规律排序的。 * 基于该特征,要么getComparator() 有值,优先; * 要么, 元素是实现 Comparable 接口。 * * 同时具备 ORDERED 的特征。 * 比如基于 SortedSet。 */

public static final int SORTED = 0x00000004;

/** * 大小固定。 * 在遍历或拆分之前,通过 estimateSize() 得到的是数据源未修改情况下的精确计数。 * 大部分 Collection 的 Spliterator 会具备该特性。 */

public static final int SIZED = 0x00000040;

/** * 数据源不为空。大部分的并发集合、队列、map。 */

public static final int NONNULL = 0x00000100;

/** * 不可变。标识遍历期间,不可添加、删除、替换。 */

public static final int IMMUTABLE = 0x00000400;

/** * 并发安全。在多线程遍历的情况下,线程安全地添加、替换、删除。 * 一般不会同时存在该特征和 SIZED 或 IMMUTABLE。 */

public static final int CONCURRENT = 0x00001000;

/** * 通过 trySplit() 拆分出的子迭代器,同时具有 SUBSIZED 和 SIZED。 * 简单来说,所有的子迭代器,无论是直接拆分的,还是间接的,都是 SIZED。 */

public static final int SUBSIZED = 0x00004000;

/** * 如果存在元素,则对其执行 action; */

boolean tryAdvance(Consumer super T> action);

/** * 对余下的元素,都执行action;直到遍历完,或遇到异常。 */

default void forEachRemaining(Consumer super T> action){

do { } while (tryAdvance(action));

}

/** * 拆分当前 Spliterator。得到的 Spliterator 遍历的元素,将不再被当前 Spliterator 所包含。 * * 如果当前是 ORDER 的,那么得到的 Spliterator 将会遍历一组相同特征(前缀)的元素。 * * 除非当前是无限元素,否则最终将得到 NULL。 * * 拆分前 estimateSize() 必定大于等于拆分后的。 * 如果是 SUBSIZED,那么拆分前的等于拆分后的总和。 * * 此方法可能由于任何原因返回null,包括空闲,在遍历开始后无法拆分,数据结构约束和效率考虑。 * * 注意: 理想的trySplit方法有效地(无遍历)将其元素精确地分成两半,允许平衡并行计算。 * 许多偏离这种理想仍然非常有效;例如,仅近似地拆分一个近似平衡的树,或者叶子节点可能包含一个或两个元素的树,无法进一步拆分这些节点。 * 然而,平衡的大偏差和/或过低效率的trySplit机制通常会导致较差的并行性能。 */

Spliterator trySplit();

/** * 得到一个用于表示 forEachRemaining 还可以遍历多少的预估值。特别特别注意,不是全部,而是剩余可遍历。 * 或者如果是无限,未知,或太大难以计算,则返回 Long.MAX_VALUE * * 如果是 SIZED,且未拆分或未部分遍历;或SUBSIZED且未部分遍历,则返回值应该是接下来遍历的准确计数。 * 否则,此估算值可能是任意不正确的,但必须按照{@link #trySplit}调用中指定的那样减小。 */

long estimateSize();

default long getExactSizeIfKnown(){

return (characteristics() & SIZED) == 0 ? -1L : estimateSize();

}

/** * 上述定义的枚举数值的或运算结果。 * 应该是不变的,重复调用也有相同的结果。 * * 拆分前后可能不同。 */

int characteristics();

default boolean hasCharacteristics(int characteristics){

return (characteristics() & characteristics) == characteristics;

}

/** * 如果此Spliterator的源由Comparator比较器为SORTED,则返回该Comparator。 * 如果源按Comparable自然顺序为SORTED,则返回null。否则,如果源不是SORTED,则抛出IllegalStateException。 */

default Comparator super T> getComparator() {

throw new IllegalStateException();

}

/** * A Spliterator specialized for primitive values. */

public interface OfPrimitive> extends Spliterator{}

/** * A Spliterator specialized for {@code int} values. * @since 1.8 */

public interface OfInt extends OfPrimitive{}

/** * A Spliterator specialized for {@code long} values. * @since 1.8 */

public interface OfLong extends OfPrimitive{}

/** * A Spliterator specialized for {@code double} values. * @since 1.8 */

public interface OfDouble extends OfPrimitive{}

}

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值