Java8新特性lambda表达式与Stream

一、概述

在程序员的日常工作中,经常会需要处理集合数据,过滤、对象转化、数据统计等。jdk8新增stream 流式编程,提供了很多方便处理集合数据的api,使得对于集合的处理更加高效简洁,提升开发效率。第一次在项目中看到lambda+stream的写法时我也是一脸懵逼,在学习了之后才发现,stream真香!代码清晰精简,从此告别for循环!下面一览其特性及常见API。

二、lambda表达式

先来上一段代码,演示lambda表达式的使用。


    public static void main(String[] args) throws Exception {
   
        Comparator<String> comparator = (s1, s2) -> s1.length() - s2.length();
        //测试一
        testComparator(comparator, "1", "11");
        //测试二
        testComparator((s1, s2) -> s1.length() - s2.length(),"1", "11");
    }

    public static void testComparator(Comparator<String> comparator, String s1, String s2){
   
        System.out.println(comparator.compare(s1, s2));
    }

测试一:通过lambda表达式创建了一个比较器。测试二:lambda表达式也可以直接作为方法参数,这样更加简化,这也是用的最多的一种方式。很多人说java8支持传递一个方法作为参数,这句话中所说的参数就是lambda表达式作为参数,比如 testComparator((s1, s2) -> s1.length() - s2.length(),“1”, “11”)。那么为什么能够实现传递一个方法呢?其实lambda表达式就是一个函数接口的实现类。比如上面的testComparator这个方法,它的第一个入参其实是Comparator接口,既然是接口,那么在使用的时候,只要传这个接口的实现类就行了。所以lambda表达式的本质就是一个对象,一个实现了一个函数接口的类的对象,传递方法作为参数的本质其实还是在传递一个对象,这就一点也不神秘了。

函数接口

上面说了,lambda表达式本质是自动的给你实现了一个接口,并且创建了对象。这个接口,必须要满足一定的规则:这个接口只有一个抽象方法。这种接口称为函数接口。为啥会有这个规则呢?想想也是,如果有多个抽象方法,那么如何确定这个lambda表达式要实现的是那个方法呢?所以只好限定接口中只有一个抽象方法。一般会在函数接口上加上@FunctionInterface注解,该注解的作用是用于编译器进行函数接口检查,如果加上该注解,却不是一个函数接口,则会报错。

类型推断

在使用lambda表达式时,我们仅仅是写了一个表达式而已,具体要实现什么接口,都是通过类型推断得出的。

方法引用

方法引用是lambda表达式的进一步简化,如果lambda表达式做的事情仅仅是调用一个已经存在的方法,并且出参入参和lambda表达式要实现的函数接口一致,那么可以用方法引用代替lambda表达式,使得语言更加简练。比如使用类名::静态方法名,类名::实例方法,实例::实例方法,构造方法::new。

二、Stream特性

1.无存储

stream不是一种新的数据结构,相当一个视图,对stream的修改并不会影响到原来的数据源。

2.函数式编程

使用stream的过程就是函数式编程的过程,在使用stream的过程中能充分体会函数式编程的简洁与高效。

3.惰式执行

对于中间操作,并没有立即执行,而是在结束操作时才真正遍历并执行中间操作。stream的执行并不是每个操作就执行遍历,而是在遇到结束操作时,一并执行,遍历一次。

4.单次消费

stream只能被消费一次,每次消费会产生新的stream,后续的操作基于新的stream来的。

三、常用操作

先创建一些数据用于举例

public class Student {
   
    private Long id;

    private String name;

    private Integer age;

    private String desc;
}
    
    private static List<Student> getStudent(){
   
        Student zhangsan  = new Student(3L, "张三", 18, "张三-desc");
        return Arrays.asList(
                zhangsan ,
                zhangsan,
                new Student(1L,"李四",20, "李四-desc"),
                new Student(2L,"王五",19, "王五-desc")
        );
    }

1.创建Stream

//集合接口有一个默认方法
Collection.stream()
//根据数组生成stream
Arrays.stream(T[])
//根据可变参数生产stream
Stream.of(T...)
//特定stream
IntStream.range()
...

2.中间操作

中间操作,在调用中间操作时,并没有立即遍历stream,只是做了标记,在结束操作时才会真正的遍历stream。

map

执行映射操作,将一个元素转换成另一个元素

<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Function 接口,接受一个参数,返回另一个元素;在stream中执行map操作,可以将元素转换另一个元素。
//举例,获取学生列表的id。
List<Long> ids 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值