lambda表达式与stream详细教程

1.Lambda表达式

1.Lambda的作用

  • 作用
    • Lambda表达式的作用就是简化代码,省略了面向对象中类和方法的书写。

2.Lambda的格式

  • 三个部分

    • 一些参数
    • 一个箭头
    • 一段代码
  • 标准格式

    (参数)->{一段代码}
    

3.案例演示

  • 线程案例演示

    public class Demo_线程演示 {
        public static void main(String[] args) {
            //匿名内部类
            //Thread t1 = new Thread(new Runnable() {
            //    @Override
            //    public void run() {
            //        for (int i = 0; i < 10000; i++) {
            //            System.out.println(i);
            //        }
            //    }
            //});
            //t1.start();
            //---------------------------------------------
            //Lambda表达式
            //()里面写的是run()方法的参数
            Thread t2 = new Thread(()->{
                for (int i = 0; i < 10000; i++) {
                System.out.println(i);
            }});
            t2.start();
    
    
            for (int i = 0; i < 10000; i++) {
                System.out.println("主线程" + i);
            }
        }
    }
    
  • 比较器案例演示

    public class Demo_比较器演示 {
        public static void main(String[] args) {
            //比较器
            ArrayList<Integer> list = new ArrayList<>();
            //添加元素
            list.add(324);
            list.add(123);
            list.add(67);
            list.add(987);
            list.add(5);
            System.out.println(list);
    
            //排序(默认从小到大)
            //Collections.sort(list);
            //Comparator是比较器,那能够让我们自己定义比较规则
            //匿名内部类
            /*
                返回值是一个整数:
                    整数如果是一个正数,就会把元素往后放
                    整数如果是一个负数,就会把元素往前放
                    整数如果是零,就认为元素相等,不移动
                参数:
                    o1 代表的是当前要存放的元素
                    o2 代表的是已经排好位置的元素
             */
            //Collections.sort(list, new Comparator<Integer>() {
            //    @Override
            //    public int compare(Integer o1, Integer o2) {
            //        return o2 - o1;
            //    }
            //});
    
            //Lambda表达式
            Collections.sort(list, (Integer o1, Integer o2)->{return o2 - o1;});
    
            //打印集合
            System.out.println(list);
        }
    }
    

4.省略格式

  • 省略规则

    1. 小括号内参数的类型可以省略
    2. 如果小括号内有且仅有一个参,则小括号可以省略
    3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号
  • 示例代码

    //Lambda表达式(不简化写法)
    Collections.sort(list, (Integer o1, Integer o2)->{return o2 - o1;});
    
    //写的越精简,阅读性就越差
    //简化写法
    Collections.sort(list, (o1, o2)-> o2 - o1);
    

5.Lambda的前提条件

  1. 使用Lambda必须具有接口,且要求接口中的抽象方法有且仅有一个。(别的方法没有影响)
  2. 使用Lambda必须具有上下文推断。

6.函数式接口

​ 如果一个接口中只有一个抽象方法,那么这个接口叫做是函数式接口。

​ @FunctionalInterface这个注解 就表示这个接口是一个函数式接口

7.小结

匿名内部类:
	可以用于类也可以用于接口,对类和接口中的方法的个数没有要求。
	
Lambda表达式:
	只能用于接口,接口中抽象方法只能有一个。
	
Lambda表达式的要求更严格,并不是所有的匿名内部类都能改成成Lambda表达式。

2.Stream流

1.概述

​ Stream用来解决之前集合的弊端。

​ Stream流相当于是流水线的操作,可以对一个集合进行多次操作。

2.获取流的方式

  • Collection单列集合
    • 调用stream()方法
  • Map双列集合
    • 调用keySet()把键转成单列集合,再调用stream()转成流
    • 调用values()把值转成单列集合,再调用stream()转成流
  • 数组
    • 数组使用Stream.of()静态方法(基本类型数组需要写成对应包装类)

3.常用方法

演示的代码:

  • 下面的方法演示都是基于这个集合:
 //创建集合
 ArrayList<String> list = new ArrayList<>();
 list.add("张翠山");
 list.add("张无忌");
 list.add("赵敏");
 list.add("张三丰");
 list.add("张三");
//转成Stream流
Stream<String> stream = list.stream();
  • 终结方法:调用了终结方法,这个流对象就不能在做其他操作了。

    • count(): 统计个数

      long count = stream.count();
      System.out.println(count);    //流中元素的个数 5
      
    • forEach() :逐一处理

      //打印流中的每个元素
      stream.forEach((String s)->{
                  System.out.println(s);
              });
      
      //把Lambda简化之后的写法:
      stream.forEach(s->System.out.println(s));
      
  • 非终结方法:支持链式编程,可以继续调用流的其他方法。

    • filter() :过滤筛选

      如果返回值是true就留下这个元素 , 如果返回值是false就过滤掉这个元素

      //筛选留下所有姓张的人
      stream.filter((String s)->{return s.startsWith("张");}).
      										forEach(s->System.out.println(s));
      //把Lambda简化之后的写法:
      stream.filter(s->s.startsWith("张")).forEach(s->System.out.println(s));
      
    • limit(): 取用前几个

      //获取流的前三个元素
      stream.limit(3).forEach(s-> System.out.println(s));
      
    • skip(): 跳过前几个

      //跳过前三个元素获取剩余的元素
      stream.skip(3).forEach(s-> System.out.println(s));
      
    • map() : 映射方法(把元素进行转换)

      //把流中的元素换成字符串对应的长度(这就相当于是一个字符串和整数的映射)
      stream.map((String s)->{return s.length();}).forEach(s-> System.out.println(s));
      
      流中的字符串会变成整数: 3 3 2 3 2
      
    • concat() :组合(把两个流拼接成一个流)

      //筛选出姓张的人(过滤掉了不姓张的人)
      //张翠山 张无忌 张三丰  张三
      Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
      //筛选出姓名是三个字的人中的前两个人
      //张翠山 张无忌
      Stream<String> s2 = list.stream().filter(s -> s.length() == 3).limit(2);
      
      //concat() :拼接(静态方法可以使用类名调用)
      Stream<String> ss = Stream.concat(s1, s2);
      //打印
      ss.forEach(s-> System.out.println(s));
      
      //上面代码可以用链式编程简化成下面写法,不过不推荐写太长:
      Stream.concat(list.stream().filter(s -> s.startsWith("张")), list.stream().filter(s -> s.length() == 3).limit(2)).forEach(s-> System.out.println(s));
      

4.练习

  • 需求:

 List<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("老子");
        one.add("庄子");
        one.add("孙子");
        one.add("洪七公");

        List<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("张三丰");
        two.add("赵丽颖");
        two.add("张二狗");
        two.add("张天爱");
        two.add("张三");



//Person类
public class Person {

    private String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "'}";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
      /*
        1. 第一个队伍只要名字为3个字的成员姓名;
        2. 第一个队伍筛选之后只要前3个人;
        3. 第二个队伍只要姓张的成员姓名;
        4. 第二个队伍筛选之后不要前2个人;
        5. 将两个队伍合并为一个队伍;
        6. 根据姓名创建 Person 对象;
        7. 打印整个队伍的Person对象信息
     */
  • 示例代码:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Demo05_练习 {
    public static void main(String[] args) {
        List<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("老子");
        one.add("庄子");
        one.add("孙子");
        one.add("洪七公");

        List<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("张三丰");
        two.add("赵丽颖");
        two.add("张二狗");
        two.add("张天爱");
        two.add("张三");

        //1. 第一个队伍只要名字为3个字的成员姓名;
        //2. 第一个队伍筛选之后只要前3个人;
        //one.stream().filter((String s)->{return s.length()==3;});

        Stream<String> s1 = one.stream().filter(s -> s.length() == 3).limit(3);


        //3. 第二个队伍只要姓张的成员姓名;
        //4. 第二个队伍筛选之后不要前2个人;
        Stream<String> s2 = two.stream().filter(s -> s.startsWith("张")).skip(2);

        //5. 将两个队伍合并为一个队伍;
        Stream<String> s3 = Stream.concat(s1, s2);

        //6. 根据姓名创建 Person 对象;
        //参数是原先的类型   返回值是要转成的类型
        //s3.map((String s)->{return new Person(s);});

        //7. 打印整个队伍的Person对象信息
        s3.map(s->new Person(s)).forEach(s-> System.out.println(s));
    }
}

5.收集(把流转成数组或集合)

以下代码基于这个集合:

List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");

//s1流里面保存的是  宋远桥 苏星河 洪七公
Stream<String> s1 = one.stream().filter(s -> s.length() == 3).limit(3);
  • 收集成List集合

    • collect(Collectors.toList());

      List<String> list = s1.collect(Collectors.toList());
      System.out.println("list" + list);
      
  • 收集成Set集合

    • collect(Collectors.toSet());

      Set<String> set = s1.collect(Collectors.toSet());
      System.out.println("set" + set);
      
  • 收集成数组

    • toArray(); 返回值是Object[]

      Object[] arr = s1.toArray();
      System.out.println(Arrays.toString(arr));
      
  • 收集到Map集合

    • collect(Collectors.toMap(键的内容,值的内容));

      //姓名作为键,姓名的长度作为值
      s1.collect(Collectors.toMap(s->s,s->s.length()));
      

版权声明:本文为weixin_44253023原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。