lambda及stream学习

Posted Vicious丶Sea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lambda及stream学习相关的知识,希望对你有一定的参考价值。

lambda及stream学习

今日板砖,见lambda,不知其然遂不以为意。后又数现之,于是乎查之,究之,学之。半晌,豁然开朗!

lambda

lambda可以理解为一个匿名函数,可以将函数作为参数传入方法中,语法:() -> {}

():用来描述参数列表

->:lambda运算符

{}:用来描述方法体

对比

//1.原始创建线程方法
      Thread thread = new Thread(new Runnable() {
          @Override
          public void run() {
              System.out.println("原始创建线程方法");
          }
      });
thread.start();
// new Thread()括号中存储的是实现了Runnable接口的一个匿名内部类;

//2. lambda创建线程方式
Thread thread1 = new Thread(()-> System.out.println("lambda线程方式"));
thread1.start();
//可以理解为,lambda创建了一个实现了Runnable接口的匿名内部类,()代表没有传递参数; System.out.println("lambda线程方式")是run()方法具体的逻辑;

lambda是针对函数式接口的一种快捷实例化方式,函数式接口为有且只有一个抽象方法的接口。使用lambda表达式,无需用对象实现接口,再继承重写抽象方法,直接通过()->{},传递参数,自定义逻辑,即可创建匿名内部类;

代码说明

  1. 无参无返回

    /**
    * 测试无返回值无参数
    */
    @FunctionalInterface
    public interface LambdaNoRNoP {
       void testNoRNop();
    }

    //无参无返回
    LambdaNoRNoP lam1 = ()->{System.out.println("hello");};//创建一个匿名内部类,重写testNoRNop()方法
    lam1.testNoRNop();

     

  2. 有参数有返回值

    /**
    * 测试有返回值多个参数
    */
    @FunctionalInterface
    public interface LambdaRMulP {
       int testRMulP(int a ,int b);
    }

    //有返回值,多个参数
    LambdaRMulP lam6 = (int a ,int b )->{ return a+b; };
    System.out.println(lam6.testRMulP(1,2));

     

代码精简

  1. 由于在接口的抽象方法中,已经定义了参数数量和类型,所以在lambda中,参数类型可以省略

  2. 如果只有一个参数,小括号可以省略

  3. 如果方法体中只有一条语句,大括号可以省略

//参数类型精简
LambdaNoRMulP lam1 = (a,b)->{System.out.println(a);};
lam1.testNoRMulP(1,2);
//小括号精简
LambdaNoRSingleP lam2 = a -> {System.out.println(a);};
//大括号精简
LambdaNoRSingleP lam3 = a -> System.out.println(a);

方法引用

可以将lambda方法的实现,指向一个完整的方法,可以理解为解耦;

语法: 方法归属者::方法名

方法归属者:如果是静态方法,归属者就是类,如果是非静态方法,归属者就是对象。

要求:参数数量和类型一级返回值要和接口中定义的方法一致

public class Test{
private static int change(int a){
      return a*2;
  }
}
LambdaRSingleP lam2 = a-> a*2;
//等同于
LambdaRSingleP lam1 = a-> change(a);//lambda的实现a*2和change()返回值一致,可以直接引用change(a)方法
//等同于
LambdaRSingleP lam3 =Test::change;//lambda表达式是传入一个int值,返回两倍的值,和Test类中的change方法逻辑一致,可以直接引用;

stream学习

stream是java8中用来操作集合的,可以理解为另类的iterator,可以对其中元素进行操作。

举例说明

//筛选集合中满足要求的数据       
List<User> userList = new ArrayList<>();
       User user1 = new User("cz1",18);
       User user2 = new User("cz2",19);
       User user3 = new User("cz3",20);
       userList.add(user1);
       userList.add(user2);

       Stream<User> stream = userList.stream();//将list转为stream流
       Stream<User> userStream = stream.filter(o -> o.getAge() > 19);//过滤流中满足要求的数据,生成新的流
       List<User> collect = userStream.collect(Collectors.toList()); // 将过滤的流转为集合

分析filter()方法源码

//filter方法传入的是一个Predicate<T>接口的实现类
Stream<T> filter(Predicate<? super T> predicate);

@FunctionalInterface  //说明是个函数时接口,抽象方法接收一个对象,返回一个boolean值
public interface Predicate<T> {

   boolean test(T t);
}
 

常用操作

数据操作

  1. map 集合对象中的某个元素再转为集合

    public static void testMap(List<User> userList){
    List<String> collect = userList.stream().map(o -> o.getName()).collect(Collectors.toList());//获取姓名集合
    List<String> collect2 = userList.stream().map(User::getName).collect(Collectors.toList());//获取姓名集合
     collect.forEach(o->System.out.println(o));//打印对象
    }

     

  2. flatMap 流元素合并

    public static void testFlatMap(List<User> userList1 , List<User> userList2){
    List<List<User>> lists = new ArrayList<>();
    lists.add(userList1);
    lists.add(userList2);
    //将集合里的元素(集合)转为流,再将流组合为一个大的集合
    List<User> collect = lists.stream().flatMap(item -> item.stream()).collect(Collectors.toList());
    //合并集合
    collect.forEach(System.out::println);
    }

     

  3. distinct 去重

        //测试distinct 去重
    public static void testDistinct(){
       List<Integer> list = new ArrayList<>();
           list.add(1);
           list.add(2);
           list.add(1);
           List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
           collect.forEach(o-> System.out.println(o));
      }

     

  4. sorted 排序

        //测试sorted 排序
    public static void testSort(){
      List<Integer> list = new ArrayList<>();
           list.add(1);
           list.add(2);
           list.add(1);
    List<Integer> collect = list.stream().sorted((o1, o2) -> o1 - o2).collect(Collectors.toList());//升序排序
    List<Integer> collect2 = list.stream().sorted((o1, o2) -> o2 - o1).collect(Collectors.toList());//降序排序
    }

     

  5. limit 限流,只取几个元素

    //测试limit限读
    public static void testLimit(){
      List<Integer> list = new ArrayList<>();
           list.add(1);
           list.add(2);
           list.add(1);
           List<Integer> collect = list.stream().limit(1).collect(Collectors.toList());
           System.out.println(collect.size());
      }

     

  6. skip 跳过读取

        //测试skip 跳过读取操作
       public static void testSkip(){
         List<Integer> list = new ArrayList<>();
           list.add(1);
           list.add(2);
           list.add(1);
           List<Integer> collect = list.stream().skip(2).collect(Collectors.toList());
           collect.forEach(o-> System.out.println(o));
      }

Collectors收集器

  1. toMap 对象元素转map集合

//测试collect收集器 toMap
public static void testCollectToMap(List<User> userList){
   //以元素的name作为k,age作为v转为map集合
Map<String, Integer> collect = userList.stream().collect(Collectors.toMap(User::getName, User::getAge));
       collect.forEach((o1,o2)-> System.out.println("K:"+o1+":V:"+o2));
}
  1. toSet 转为不可重复集合

        //测试collect收集器 toSet //不可重复
       public static  void testCollectToSet(List<Integer>list){
           Set<Integer> collect = list.stream().collect(Collectors.toSet());
           collect.forEach(System.out::println);
      }

     

  2. groupingBy 集合对象分组

        //测试groupingBy 分组
       public static void testCollectGroupingBy(List<User> list){
           Map<String, List<User>> collect = list.stream().collect(Collectors.groupingBy(User::getName));
           collect.forEach((o1,o2)-> System.out.println("K:"+o1+"--V:"+o2));
      }

     

  3. maxBy 取集合最大元素

        //测试maxBy 获取最大元素
       public static void testMaxBy(List<User> list){
           //获取user对象中年龄最大的
    Optional<User> collect = list.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge()));
           System.out.println(collect.get());//拿到user对象
      }

     

  4. minBy 取集合最小元素

        //测试minBy 获取最小元素
       public static void testMinBy(List<User> list){
    Optional<User> collect = list.stream().collect(Collectors.minBy((o1, o2) -> o1.getAge() - o2.getAge()));
           System.out.println(collect.get());
      }

     

  5. mapping 获取元素的某个属性的集合

        //测试mapping隐射取值
       public static void testMapping(List<User> list){
      List<String> collect = list.stream().collect(Collectors.mapping(User::getName,Collectors.toList()));
           //等同于
        List<String> collect1 = list.stream().map(o -> o.getName()).collect(Collectors.toList());
           collect1.forEach(o-> System.out.println(o));
      }

     

  6. match 判断集合是否匹配

        //测试match
       //allMatch--集合内所有元素都满足返回true
       //anyMatch--任意一个元素满足就返回true
       //noneMatch--没有元素满足就返回true
       public static void testMatch(List<User> list){
           public static void testMatch(List<User> list){
           boolean b = list.stream().allMatch(o -> o.getAge() > 19);//判断集合中的所有用户年龄是否都大于19
           System.out.println(b);
      }
      }

     

  7.  

以上是关于lambda及stream学习的主要内容,如果未能解决你的问题,请参考以下文章

JAVA8之lambda表达式详解,及stream中的lambda使用

还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下

lambda表达式与Stream流(非io)

Java8特性详解 lambda表达式 Stream

java8新特性学习:stream与lambda

Lambda学习---StreamApi使用