• java基础复习(3)


    写在前面

    前面学习了Lambda表达式,现在来学习一下根据Lambda表达式衍生出的Stream流和方法引用。

    Stream流

    引子

    一提到流,可能都只会想到IO流。实际上,流不一定是IO流,今天就来学习一下Stream流。首先我们来看一段传统的集合过滤代码:

            // 创建一个List集合,存储姓名
            List<String> list = new ArrayList<>();
            list.add("张无忌");
            list.add("周芷若");
            list.add("赵敏");
            list.add("张强");
            list.add("张三丰");
    
            // 对集合中的元素进行过滤,只要以张开头头的元素都存到一个新的集合中
            List<String> listA = new ArrayList<>();
            for (String s : list) {
                if(s.startsWith("张")){
                    listA.add(s);
                }
            }
            // 对listA集合进行过滤,只要姓名长度为3的人,再存到一个新集合中
            List<String> listB = new ArrayList<>();
            for (String s : listA) {
                
                if (s.length() == 3) {
                    listB.add(s);
                }
            }
            // 遍历listB集合
            for (String s : listB) {
                System.out.println("s = " + s);
            }
    

    在这段代码中,我们先选出了姓张的,再选出了姓名长度为3的,最后使用增强for循环进行了输出。可以看到代码还是很多的。那么我们如果使用Stream流呢?

            // 创建一个List集合,存储姓名
            List<String> list = new ArrayList<>();
            list.add("张无忌");
            list.add("周芷若");
            list.add("赵敏");
            list.add("张强");
            list.add("张三丰");
            // 对集合中的元素进行过滤,只要以张开头头的元素都存到一个新的集合中
            // 对listA集合进行过滤,只要姓名长度为3的人,再存到一个新集合中
            // 遍历listB集合
            list.stream()
                    .filter(name -> name.startsWith("张"))
                    .filter(name -> name.length() == 3)
                    .forEach(name -> System.out.println(name));
    

    可以看到,我们的代码被极大简化了。这就是结合了Stream流和Lambda表达式给我们带来的编程便利。

    获取Stream流

    既然这东西这么好,那我们如何获取和使用呢?这里我们学习以下两种获取方法:

    1. 使用集合直接获取
    2. 使用Stream.of静态方法获取。

    直接上例子看看:

        public static void main(String[] args) {
            // 把集合转换成Stream流
            List<String> list = new ArrayList<>();
            Stream<String> stream1 = list.stream();
            Set<String> set = new HashSet<>();
            Stream<String> stream2 = set.stream();
            Map<String,String> map = new HashMap<>();
            // 获取键,存储到一个Set集合中
            Set<String> keySet = map.keySet();
            Stream<String> stream3 = keySet.stream();
            // 获取值,存储到一个Collection集合中
            Collection<String> values = map.values();
            Stream<String> stream4 = values.stream();
            // 获取键值对(键与值的映射关系 entrySet)
            Set<Map.Entry<String, String>> entries = map.entrySet();
            Stream<Map.Entry<String, String>> stream5 = entries.stream();
    
            // 把数组转换为Stream流
            Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
            // 可变参数可以传递数组
            Integer[] arr = {1,2,3,4,5};
            Stream<Integer> stream7 = Stream.of(arr);
            String[] arr2 = {"a","bb","cccc"};
            Stream<String> stream8 = Stream.of(arr2);
        }
    

    可以看到,Stream流的获取还是十分简单的。那么我们可以用Stream流做到什么呢?

    Stream流里的常用方法

    首先要了解,Stream流的方法有两种,一种叫延迟方法(即返回的还是Stream接口自身),一种叫终结方法,返回的类型就不再是Stream接口自身了。

    • forEach(终结方法)

      虽然叫forEach,但和增强for循环还是不太一样的。我们来看看怎么使用:

            // 获取一个Stream流
              Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六");
              // 使用Stream流中的方法
              stream.forEach(name -> System.out.println("name = " + name));
              System.out.println("===========");
      
    • filter(延迟方法)

      这是我们刚才使用的filter方法,我们来再使用一次看看:

              // 创建Stream流
              Stream<String> stream1 = Stream.of("张三锋", "李四", "王五", "赵六");
              // 对Stream流中的元素进行过滤出姓张的
              Stream<String> stream2 = stream1.filter(name -> name.startsWith("张"));
              // 遍历stream1
              stream2.forEach(name -> System.out.println(name));
      
    • map(延迟方法)

      map方法,可以进行集合进行转换,如下使用:

              // map方法
              // 获取Stream流
              Stream<String> stream3 = Stream.of("1", "2", "3");
              // 使用map方法将字符串转换为Ineger类型的整数
              Stream<Integer> stream4 = stream3.map(s -> Integer.parseInt(s));
      
    • collect(终结方法)

      首先我们要有一个对象:

      public class Person {
          
          private String name;
          private int age;
      }
      

      里面的get,set方法和构造方法就省略了。

      然后我们使用collect方法:

              List<Person> list1 = new ArrayList<>();
              list1.add(new Person("王五",15));
              list1.add(new Person("赵四",18));
              list1.add(new Person("赵六",20));
              Map<String, Integer> map = list1.stream().collect(Collectors.toMap(p -> p.getName(), p->p.getAge()));
      

      可以看到,我们使用Stream流可以很方便的将一个List转换成了一个map。同样的,也可以先处理后转换成List,Set等等。具体的使用请在实际使用中练习吧。

    方法引用

    引子

    上面我们的使用,实际上已经十分简单了,但能不能更简单呢?可以看到有时候我们的Lambda表达式都只用了一句话,比如下面的这个:

    .forEach(name -> System.out.println(name));
    

    这里面的name实际上没有任何意义,只是我们定义的一个形参而已。我们想要的就是输出这个形参罢了。那么我们可以写成下面这样:

    .forEach(System.out::println);
    

    是不是更加简单了呢?

    介绍和使用

    这里出现了一个新的符号,双冒号。学过C++的可能会知道,这个符号在C++里叫做作用域符,有一种用法和上面也很像,如类::变量。但在java中这个叫做引用运算符,如果在Lambda表达式中要表达的函数方法已经存在,那么就可以使用这个符号来调用他。

    事实上,我们自己定义的方法也可以用,比如上面我们提到的collect方法,我们也可以用方法引用这么写:

            Map<String, Integer> map = list1.stream().
                    collect(Collectors.toMap(Person::getName, Person::getAge));
    

    看起来是不是要简单的多了呢。

    小结

    方法引用的使用方法和场景多种多样,这里只介绍最基本的用法,具体的就请在日后使用到时再了解吧。

    总结

    这里学习的这些,都是JDK8里的新特性。通过这些新特性的学习,我们可以让代码更加的优雅了。

  • 相关阅读:
    Android将ScrollView移动到最底部
    Android权限之sharedUserId和签名
    python接口使用及工具函数
    python模块(json、os、sys、random、string、time、hashlib)
    python内置函数
    python模块、函数变量及递归
    python数据类型集合及函数
    python文件操作及修改
    python字符类型操作及文件操作
    jmeter压测
  • 原文地址:https://www.cnblogs.com/wushenjiang/p/13358181.html
Copyright © 2020-2023  润新知