zoukankan      html  css  js  c++  java
  • Java8集合框架——集合的遍历(迭代)

      本文主要梳理 Java 集合框架常见的遍历/迭代方式,如下:

    1、List 的遍历方式

      List 的遍历主要有以下几种方式:

      其中 2、3、5 本质上可以说是一样的使用 Iterator 迭代器。而 ListIterator 则是 Iterator 的一个变种(双向迭代, 可以进行 add、remove、set、定位当前索引),使用如下:

    public static void main(String[] args) {
        List<String> strList = new ArrayList<>();
        /// List<String> strList = new LinkedList<>();
        strList.add("1st");
        strList.add("2nd");
        strList.add("3rd");
        strList.add("4th");
    
        // 1、 索引下标 for 循环
        // 注意:对于链表形式的实现,每次都是 O(N),总的是(O(N*N)),效率较低
        System.out.println("for 循环");
        for (int i = 0, length = strList.size(); i < length; i++) {
            System.out.println(strList.get(i));
        }
    
        // 2、 增强的 for 循环,内部是迭代器实现
        // https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2
        System.out.println("增强的 for 循环");
        for (String str : strList) {
            System.out.println(str);
        }
    
        // 3.1、 Iterator 迭代器 while 形式
        System.out.println("Iterator 迭代器 while 形式");
        Iterator<String> itr = strList.iterator();
        while (itr.hasNext()) {
            String string = itr.next();
            System.out.println(string);
        }
        // 3.2、 Iterator 迭代器 for 形式
        System.out.println("Iterator 迭代器 for 形式");
        for (Iterator<String> iterator = strList.iterator(); iterator.hasNext();) {
            String string = iterator.next();
            System.out.println(string);
        }
    
        // 4、 ListIterator 双向迭代器, Iterator 的子类型, List 集合特有的方式
        // ListIterator 双向, 还可以进行 add、remove、set、定位当前索引
        // ArrayList 和 LinkedList 各自的内部类实现
        ListIterator<String> listItr = strList.listIterator();
        System.out.println("ListIterator 反向迭代1");
        // 这里并没有上一个,所以没有
        while (listItr.hasPrevious()) {
            String string = listItr.previous();
            System.out.println(string);
        }
        System.out.println("ListIterator 正向迭代");
        while (listItr.hasNext()) {
            String string = listItr.next();
            System.out.println(string);
        }
        System.out.println("ListIterator 反向迭代2");
        while (listItr.hasPrevious()) {
            String string = listItr.previous();
            System.out.println(string);
        }
    
        // 5、 Java 8 Lambda 迭代方式
        // 本质上还是增强的 for 循环(内部是迭代器实现),将对应的操作封装到 Consumer 里面
        System.out.println("Java 8 Lambda 迭代方式");
        strList.forEach(str -> System.out.println(str));
        System.out.println("=-=");
        strList.forEach(System.out::println);
        strList.forEach(str -> {
            System.out.println("---");
            System.out.println(str);
        });
        // 比较完整的写法,其实就是自定义 Consumer 接口的实现类,重写 accept 方法
        strList.forEach(new Consumer<String>() {
            @Override
            public void accept(String str) {
                System.out.println("-=-");
                System.out.println(str);
            };
        });
    
        // 6、 Java 8 Stream 迭代方式
        System.out.println("Java 8 Stream 迭代方式");
        strList.stream().forEach(System.out::println);
        System.out.println("-~-");
        strList.stream().forEach(str -> System.out.println(str));
        strList.stream().forEach(str -> {
            System.out.println("===");
            System.out.println(str);
        });
        // 也可以使用自定义 Consumer 接口的实现类的方式
    }

     注:因 LinkedList 内部为双向链表实现,通过 LinkedList.get(index) 获取元素每次都是 O(N) ,效率相对较低,建议使用 Iterator 的方式(增强的 for 循环或者直接使用 Iterator)。

    参考:Ways to iterate over a list in Java:https://stackoverflow.com/questions/18410035/ways-to-iterate-over-a-list-in-java

    2、Set 的遍历方式

      对比 List 可知,Set 没有 get(index) 的方式,也没有 ListIterator 双向迭代器 ,其他的都是类似的,Set 的遍历主要有以下几种方式:

      使用代码如下:

    public static void main(String[] args) {
        Set<String> strSet = new HashSet<>();
        // Set<String> strSet = new LinkedHashSet<>();
        // Set<String> strSet = new TreeSet<>();
        strSet.add("1st");
        strSet.add("2nd");
        strSet.add("3rd");
        strSet.add("4th");
    
        // 1、 增强的 for 循环
        System.out.println("增强的 for 循环");
        for (String str : strSet) {
            System.out.println(str);
        }
    
        // 2.1、 Iterator 迭代器 while 形式
        System.out.println("Iterator 迭代器 while 形式");
        Iterator<String> itr = strSet.iterator();
        while (itr.hasNext()) {
            String string = itr.next();
            System.out.println(string);
        }
        // 2.2、 Iterator 迭代器 for 形式
        System.out.println("Iterator 迭代器 for 形式");
        for (Iterator<String> iterator = strSet.iterator(); iterator.hasNext();) {
            String string = iterator.next();
            System.out.println(string);
        }
    
        // 3、 Java 8 Lambda 迭代方式
        // 本质上还是增强的 for 循环(内部是迭代器实现),将对应的操作封装到 Consumer 里面
        System.out.println("Java 8 Lambda 迭代方式");
        strSet.forEach(str -> System.out.println(str));
    
        // 4、 Java 8 Stream 迭代方式
        System.out.println("Java 8 Stream 迭代方式");
        strSet.stream().forEach(System.out::println);
        System.out.println("-~-");
        strSet.stream().forEach(str -> System.out.println(str));
    }

      另外还有一些方式是先转成 Array 再遍历。。。

    参考:How to Iterate over a Set/HashSet without an Iterator?:https://stackoverflow.com/questions/12455737/how-to-iterate-over-a-set-hashset-without-an-iterator

    3、Map 的遍历方式

      Map 比较特殊,它是 k-v 对,遍历也会相对不一样。这里总结几种遍历方式:

    • 1、Map.Entry + foreach 的迭代方式
    • 2、Map.Entry + Iterator 的迭代方式
    • 3、keySet + foreach 的迭代方式
    • 4、keySet + Iterator 的迭代方式
    • 5、Iterable.forEach + Lambda
    • 6、Stream.forEach

      使用如下:

    public static void main(String[] args) {
        Map<String, String> strMap = new HashMap<>();
        // Map<String, String> strMap = new LinkedHashMap<>();
        // Map<String, String> strMap = new TreeMap<>();
        strMap.put("1", "1st");
        strMap.put("2", "2nd");
        strMap.put("3", "3rd");
        strMap.put("4", "4th");
    
        // 1、 Map.Entry + foreach 的迭代方式
        System.out.println("Map.Entry + foreach 迭代方式");
        for (Map.Entry<String, String> entry : strMap.entrySet()) {
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
        
        // 2.1、  Map.Entry + Iterator 的 while 迭代方式
        System.out.println("Map.Entry + Iterator 的 while 迭代方式");
        Iterator<Map.Entry<String, String>> mapItr = strMap.entrySet().iterator();
        while (mapItr.hasNext()) {
            Map.Entry<String, String> entry = mapItr.next();
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    
        // 2.2、  Map.Entry + Iterator 的 for 迭代方式
        System.out.println("Map.Entry + Iterator 的 for 迭代方式");
        for (Iterator<Map.Entry<String, String>> mapItrs = strMap.entrySet().iterator(); mapItrs.hasNext();) {
            Map.Entry<String, String> entry = mapItrs.next();
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
        
        // 3、 keySet + foreach 的迭代方式
        System.out.println("keySet + foreach 的迭代方式");
        Set<String> keySet = strMap.keySet();
        for (String key : keySet) {
            System.out.println(key + "=" + strMap.get(key));
        }
        
        // 4、 keySet + Iterator 的迭代方式
        System.out.println("keySet + Iterator 的迭代方式");
        Iterator<String> strItr = strMap.keySet().iterator();
        while (strItr.hasNext()) {
            String key = strItr.next();
            System.out.println(key + "=" + strMap.get(key));
        }
        
        // 以下这些都可以通过自定义 Consumer 接口的实现类来处理
        // 5、 Iterable.forEach + Lambda (Java 8 Lambda 迭代方式)
        System.out.println("Iterable.forEach + Lambda (Java 8 Lambda 迭代方式)");
        strMap.forEach((k, v) -> System.out.println(k + "=" + v));
        
        // 6、 Stream.forEach ( Java 8 Stream 迭代方式)
        System.out.println("Stream.forEach ( Java 8 Stream 迭代方式)");
        strMap.entrySet().forEach((entry) -> System.out.println(entry.getKey() + "=" + entry.getValue()));
    }

      

    4、总结

      总的来说,基本上就是 : 索引 + 增强的 foreach + Iterator + Iterable.forEach + Stream.forEach

    5、参考

  • 相关阅读:
    使用numpy生成二维正态分布
    %matplotlib inline的含义
    The following packages will be SUPERCEDED by a higher-priority channel是什么意思?
    conda命令详解
    软件包,API,SDK的区别
    IP组网实验(使用Cisco Packet Tracer路由器模拟软件)
    MAC地址表、ARP缓存表、路由表及交换机、路由器基本原理
    K'ed by TNT team是什么意思?
    使用Applescript、Automator和AfredWorkflow实现流式工作
    Redux源码分析之createStore
  • 原文地址:https://www.cnblogs.com/wpbxin/p/13706678.html
Copyright © 2011-2022 走看看