温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java中迭代map的方式有哪些

发布时间:2021-09-05 12:50:12 来源:亿速云 阅读:214 作者:小新 栏目:开发技术

这篇文章主要介绍了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));
            }
    
        }
    }

    感谢你能够认真阅读完这篇文章,希望小编分享的“java中迭代map的方式有哪些”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI