java迭代器原理及迭代map的四种方式

 更新时间:2021年09月03日 15:14:28   作者:dandeseed  
本文我们将了解一下java迭代器原理及其在Java中迭代Map各种不同方法。具有一定的参考价值,感兴趣的可以了解一下

迭代器原理:

什么是迭代器,使用迭代器的好处?

迭代器就是用来遍历集合中对象的东西,也就是说,对于集合,我们不像对原始数组那样通过直接访问元素来迭代的,而是通过迭代器来遍历对象。这么做的好处是将对于集合类型的遍历行为与被遍历集合对象分离,这样以来,就不需要关心该集合类型的具体实现是怎么样的。只要获取这个集合对象的迭代器便可以遍历这个集合中的对象。而像遍历对象顺序以及怎么访问对象元素这些细节,全部由它自己的迭代器来处理。

迭代器怎么实现的?

首先集合要先实现iterable接口来表示此对象是可以进行迭代的。而实现iterable接口的对象实现了iterator方法,这个方法返回了一个Iterator对象。一个迭代器对象需要Iterator接口中的方法:hasNext(),next(),remove()。remove()方法会删除最近一次调用的元素,如果remove()之前没有调用next()的话直接调用remove()会产生报错信息(IllegalStateException)。我们在进行对集合对象迭代的时候,next()会返回当前对象第一个对象并返回,然后next会指向下一个元素,hasNext方法就是看这个指针后面还有没有元素了。

迭代器的陷阱?

使用for迭代的时候不可以使用集合进行remove操作。这时候需要使用迭代器进行迭代,然后使用迭代器中的remove方法进行删除。

为什么会产生这样的错误?

remove()方法在删除元素的时候,还会修改一个修改次数的标志位modCount,如果iterator的expectedModCount与modCount的大小不相等时,会抛出一个ConcurrentModificationException异常。modCount的目的主要是为了防止当前对象迭代过程中存在其他线程对当前对象的修改。

// iterable接口源代码

public interface Iterable<T> {
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    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);
    }
}

// iterator接口源代码

public interface Iterator<E> {
    /**
    * 如果迭代拥有更多元素,那么返回true
    */
    boolean hasNext();
    /**
    * 返回iteration中的下一个元素
    */
    E next();
    /**
    * 如果删除一个集合中的元素没有调用这个方法,二十直接中集合中删除,那么这个迭代器的行为没有被指定
    */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    /**
    * 遍历集合中的剩余元素(如果之前调用了两次next()那么只会遍历集合中剩余元素
    * 使用案例:
    * Iterator<Integer> it = map.keySet().iterator();
        it.next();
        it.next();
        it.forEachRemaining(System.out::println);
    */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

HashMap中实现迭代的核心代码:

        final Node<K,V> nextNode() {
            Node<K,V>[] t;
            Node<K,V> e = next; // 对象属性中的next是下一个值
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            // next = e.next 如果e.next为null,那么继续找数组下一个不为null的值
            if ((next = (current = e).next) == null && (t = table) != null) {
                do {} while (index < t.length && (next = t[index++]) == null);
            }
            return e;
        }
        public final void remove() {
            Node<K,V> p = current;
            if (p == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            current = null;
            K key = p.key;
            removeNode(hash(key), key, null, false, false);
            expectedModCount = modCount;

遍历map的四种方式

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;

public class MapTest {
    public static void main(String[] args) {
        HashMap<Integer,Integer> map = new HashMap();
        map.put(0,1);
        map.put(2,2);
        map.put(1,2);
        map.put(4,5);
        map.put(3,4);
        // 遍历hashmap entry foreach
        Set<Map.Entry<Integer,Integer>> ent = map.entrySet();
        for(Map.Entry<Integer,Integer> entry:ent){
            System.out.println(entry.getKey()+"  :  "+entry.getValue());
            //map.remove(0);
        }
        System.out.println();
        // 通过keySet或者values()遍历
        Set<Integer> set = map.keySet();
        for(Integer key:set){
            System.out.println(key+"  --  "+map.get(key));
        }
        Collection<Integer> set1 = map.values();
        for(Integer val:set1){
            System.out.println(val);
        }
        System.out.println();
        // iterator原理是什么 通过iterator遍历map
        Iterator<Map.Entry<Integer,Integer>> iter = map.entrySet().iterator();
        while(iter.hasNext()){
            Map.Entry entry = iter.next();
            System.out.println(entry.getKey()+"  :  "+entry.getValue());
            iter.remove();
        }
        System.out.println();
        Iterator<Integer> keys = map.keySet().iterator();
        while(keys.hasNext()){
            int k = keys.next();
            System.out.println(k+" -- "+ map.get(k));
        }

    }
}

参考链接:https://blog.csdn.net/fuzhongmin05/article/details/72460658

到此这篇关于java迭代器原理及迭代map的四种方式的文章就介绍到这了,更多相关java迭代map内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot+Eureka实现微服务负载均衡的示例代码

    SpringBoot+Eureka实现微服务负载均衡的示例代码

    这篇文章主要介绍了SpringBoot+Eureka实现微服务负载均衡的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • 解析JDK14中的java tools简介

    解析JDK14中的java tools简介

    这篇文章主要介绍了JDK14中的java tools简介,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Java多线程编程实战之模拟大量数据同步

    Java多线程编程实战之模拟大量数据同步

    这篇文章主要介绍了Java多线程编程实战之模拟大量数据同步,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-02-02
  • springboot整合mybatis-plus代码生成器的配置解析

    springboot整合mybatis-plus代码生成器的配置解析

    这篇文章主要介绍了springboot整合mybatis-plus代码生成器的配置解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Java简单实现对一串数字采用相应的加密策略后传输

    Java简单实现对一串数字采用相应的加密策略后传输

    下面小编就为大家带来一篇Java简单实现对一串数字采用相应的加密策略后传输。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    下面小编就为大家分享一篇Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • SpringBoot详细讲解异步任务如何获取HttpServletRequest

    SpringBoot详细讲解异步任务如何获取HttpServletRequest

    在使用框架日常开发中需要在controller中进行一些异步操作减少请求时间,但是发现在使用@Anysc注解后会出现Request对象无法获取的情况,本文就此情况给出完整的解决方案
    2022-04-04
  • EDI中JAVA通过FTP工具实现文件上传下载实例

    EDI中JAVA通过FTP工具实现文件上传下载实例

    这篇文章主要介绍了EDI中JAVA通过FTP工具实现文件上传下载实例,具有一定的参考价值,有需要的可以了解一下。
    2016-11-11
  • 详解使用spring validation完成数据后端校验

    详解使用spring validation完成数据后端校验

    这篇文章主要介绍了详解使用spring validation完成数据后端校验,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java Map.Entry的使用方法解析

    Java Map.Entry的使用方法解析

    这篇文章主要介绍了Java Map.Entry的使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论