首页 > 其他分享 >Iterator和Iterable

Iterator和Iterable

时间:2024-07-13 23:20:09浏览次数:3  
标签:return Iterator int void new public Iterable

Java遍历List有三种方式

public static void main(String[] args) {
    List<String> list = new ArrayList<>();

    // for循环
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i) + ", ");
    }

    // for-each,实际也是Iterator
    for (String s : list) {
        System.out.println(s + ", ");
    }

    // 迭代器
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        System.out.println(it.next() + ", ");
    }
}

Iterator源码

public interface Iterator<E> {
    // 判断集合中是否存在下一个对象
    boolean hasNext();
    
    // 返回集合中的下一个对象,并将访问指针移动一位
    E next();
    
    // 删除集合中调用next()方法返回的对象
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    
    default void forEach(Consumer<? super T> action) {
    	Objects.requireNonNull(action);
    	for (T t : this) {
        	action.accept(t);
    	}
	}
}

  • 它对 Iterable 的每个元素执行给定操作,具体指定的操作需要自己写Consumer接口通过accept方法回调出来。
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
list.forEach(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) {
        System.out.println(integer);
    }
});

  • List 的关系图谱中并没有直接使用 Iterator,而是使用 Iterable 做了过渡
public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

ArrayList重写了Iterable的iterator方法

public Iterator<E> iterator() {
    return new Itr();
}
private class Itr implements Iterator<E> {
    // 下个元素的索引
    int cursor;       // index of next element to return
    // 上个元素的索引
    int lastRet = -1; // index of last element returned; -1 if no such
    // 预期的结构性修改次数
    int expectedModCount = modCount;

    Itr() {}

    // 判断是否还有下个元素
    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    // 获取下个元素
    public E next() {
        checkForComodification();
        // 记录当前迭代器的位置
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        // 获取 ArrayList 对象的内部数组
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        // 将游标位置加 1,为下一次迭代做准备
        cursor = i + 1;
        // 记录上一个元素的索引
        return (E) elementData[lastRet = i];
    }

    // 删除最后一个返回的元素,迭代器只能删除最后一次调用 next 方法返回的元素
    public void remove() {
        // 如果上一次调用 next 方法之前没有调用 remove 方法,则抛出 IllegalStateException 异常
        if (lastRet < 0)
            throw new IllegalStateException();
        // 检查在最后一次调用 next 方法之后是否进行了结构性修改
        checkForComodification();

        try {
            // 调用 ArrayList 对象的 remove(int index) 方法删除上一个元素
            ArrayList.this.remove(lastRet);
            // 将游标位置设置为上一个元素的位置
            cursor = lastRet;
            // 将上一个元素的索引设置为 -1,表示没有上一个元素
            lastRet = -1;
            // 更新预期的结构性修改次数
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
        checkForComodification();
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}
  • Map 就没办法直接使用 for-each,因为 Map 没有实现 Iterable 接口,只有通过 map.entrySet()map.keySet()map.values() 这种返回一个 Collection 的方式才能 使用 for-each。

LinkedList的父类 AbstractSequentialList重写 Iterable 接口的 iterator 方法

  • LinkedList 并没有直接重写 Iterable 接口的 iterator 方法,而是由它的父类 AbstractSequentialList 来完成
public Iterator<E> iterator() {
    return listIterator();
}
  • LinkedList重写了listIterator方法
public ListIterator<E> listIterator(int index) {
    checkPositionIndex(index);
    return new ListItr(index);
}
// 在遍历List 时可以从任意下标开始遍历,而且支持双向遍历。
// Iterator 不仅支持 List,还支持 Set,但 ListIterator 就只支持 List
public interface ListIterator<E> extends Iterator<E> {

    boolean hasNext();

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    void remove();

    void set(E e);

    void add(E e);
}
  • LinkedList的逆序遍历
private class DescendingIterator implements Iterator<E> {
    // 使用 ListItr 对象进行逆向遍历。
    private final ListItr itr = new ListItr(size());

    // 判断是否还有下一个元素。
    public boolean hasNext() {
        return itr.hasPrevious();
    }

    // 获取下一个元素。
    public E next() {
        return itr.previous();
    }

    // 删除最后一个返回的元素。
    public void remove() {
        itr.remove();
    }
}

标签:return,Iterator,int,void,new,public,Iterable
From: https://www.cnblogs.com/sprinining/p/18300962

相关文章

  • PHP获取目录中的全部内容RecursiveDirectoryIterator
    PHP获取目录中的全部内容RecursiveDirectoryIterator码农老张 posted@2021-03-3109:44 这次我们来介绍一个SPL库中的目录迭代器,它的作用其实非常简单,从名字就可以看出来,就是获取指定目录下的所有内容。之前我们要遍历目录获取目录及目录下的所有文件一般是需要进行递归遍......
  • 【知识点】C++ STL 中的 iterator_traits 类
    iterator_traits讲解基本定义iterator_traits是一个模板类,用于提供与迭代器相关的类型信息。以下是iterator_traits的基本定义:#include<iterator>template<typenameIterator>structiterator_traits{typedeftypenameIterator::difference_typediffere......
  • Uncaught TypeError: Invalid attempt to spread non-iterable instance.
    1、报错信息:报错UncaughtTypeError:Invalidattempttospreadnon-iterableinstance.Inordertobeiterable,non-arrayobjectsmusthavea[Symbol.iterator]()method.at_nonIterableSpread(OgPanel.js:20:39)at_toConsumableArray(OgPanel.js:18:131)......
  • 【设计模式】迭代器模式 ——详解Iterator、foreach与for循环的区别
    参考:B站UP主动力节点迭代器模式定义:提供方法,顺序访问集合对象中的各个元素,而又不暴露对象的内部表示。为遍历不同的集合结构提供统一的接口,分离了集合对象的遍历行为。tips:Iterator迭代器本身就是JDK按照该模式设计的迭代器,通常情况下,我们都是直接使用JDK提供的。此处......
  • Python学习迭代器(Iterator)
    一、可迭代的对象(Iterable)1、定义:可以直接用在循环的数据类型,如list,tuple,dict,set,str,还有generator(生成器),和带yield的函数,这些直接可以用在循环的对象统称为可迭代对象(Iterable)fromcollectionsimportIterableprint(isinstance([],Iterable))print(isin......
  • 【强化学习】A grid world 值迭代算法 (value iterator algorithm)
    强化学习——值迭代算法代码是在jupyternotebook环境下编写只需要numpy和matplotlib包。此代码为学习赵世钰老师强化学习课程之后,按照公式写出来的代码,对应第四章第一节valueiteratoralgorithm可以做的实验:调整gama值观察策略的变化调整惩罚值(fa)的大小观察......
  • Iterator 和 ListIterator 有什么区别?
    前言Iterator和ListIterator都是Java集合框架中的迭代器接口,它们都可以用于遍历集合中的元素。ListIterator继承自Iterator接口,因此ListIterator可以用于任何实现了Iterator接口的集合,如List和Set。以下是两者的主要区别:原始集合类型的差别Iterator可以遍历Collection中的元......
  • ES6学习之路:迭代器Iterator和生成器Generator
    迭代器一、知识背景什么是迭代器迭代器就是在一个数据集合中不断取出数据的过程迭代和遍历的区别遍历是把所有数据都取出迭代器注重的是依次取出数据,它不会在意有多少数据,也不会保证能够取出多少或者能够把数据都取完。比如斐波那契额数列,就可以使用迭代器进行无限......
  • Day25 迭代器之Iterator底层
    Day25迭代器之Iterator底层一、迭代器1、概念:迭代器(Iterator)是一种用于遍历集合(Collection)元素的接口,它提供了统一的方式来访问集合中的元素,而不暴露集合的内部结构。通过迭代器,我们可以依次访问集合中的每个元素,进行遍历和操作。2、使用步骤:获取集合的迭代器:Iterat......
  • 【python】(02)初识迭代器Iterator
    系列文章回顾【python】(01)初识装饰器Decorator【python】(02)初识迭代器Iterator文章目录一.迭代器的定义二.迭代器的作用三.实际代码示例四.使用注意事项五.常见问题迭代器是Python中非常重要的概念,通过灵活运用迭代器可以实现高效的数据遍历和处......