java8新特性

1.Lambda表达式

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

1.1语法

Lambda 表达式:在Java 8 语言中引入的一种新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符 或箭头操作符。它将 Lambda 分为两个部分:

左侧:指定了 Lambda 表达式需要的参数列表 (其实就是接口中的抽象方法的形参列表)

**右侧:**指定了 Lambda 体,是抽象方法的实现逻辑,(其实就是重写的抽象方法的方法体)

2.函数式接口

什么是函数式(Functional)接口

只包含一个抽象方法的接口,称为函数式接口。

你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明)。

我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

在java.util.function包下定义了Java 8 的丰富的函数式接口

2.1理解函数式接口

Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,也即**java不但可以支持OOP还可以支持OOF(面向函数编程) **

在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口。

简单的说,在Java8中,**Lambda表达式就是一个函数式接口的实例。**这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-srll7iGn-1665623177848)(C:\Users\王率宇\AppData\Roaming\Typora\typora-user-images\image-20221009110844146.png)]

img

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。

要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!((针对于情况1和情况2))

格式:使用操作符 “::” 将类(或对象) 与 方法名分隔开来。

如下三种主要使用情况:

对象::实例方法名

类::静态方法名

类::实例方法名
函数式接口:

3.创建流

单列集合:

集合对象.stream( )

List<Integer> list = new ArrayList();
Stream<Integer> stream = list.stream();

双列集合:

转化为单列集合再进行创建

Map<String,Integer> map = new HashMap();
map.put("蜡笔小新",19);
Stream<Map.Entry<String,Integer>> stream = map.entrySet().stream();

数组:

Array.stream(数组)

int[] arr = {1,2,3,4,5};
Stream<Integer> arrStream = Arrays.stream(arr);

4.中间操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jOoFELH6-1665623177849)(C:\Users\王率宇\AppData\Roaming\Typora\typora-user-images\image-20221009155147872.png)]

filter

// 对作家名字的长度进行筛选
List<Author> author = new ArrayList();
authors.stream
	.filter(author->author.getName().length()>1)
    //中间操作之后一定要加入一个终结操作
    .forEach(author->sout(author.getName()));

map

把流当中的元素进行转换或计算、

 @Test
    public void test04(){
        List<Author> authors = getAuthors();
        authors.stream()
                .map(new Function<Author, String>() {
                    @Override
                    public String apply(Author author) {
                        return author.getAge().toString();
                    }
                })
                .map(new Function<String, Integer>() {
                    @Override
                    public Integer apply(String s) {
                        return Integer.parseInt(s)+10;
                    }
                })
                .forEach(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer s) {
                        System.out.println(s);
                    }
                });
    }

sorted

sorted 在没有传参的情况下 需要对象去实现comparable 接口

    /**
     * 使用sorted时比较整个元素时,要实现比较接口,并重写方法
     */
    @Override
    public int compareTo(Author o) {
        // return 0; // 这里是如何比较
        // 0表示年纪一样大,负数表示传入的大
        // 这里sorted如果输出的是降序,你就把这俩顺序对换就可以了,不用记忆
        return o.getAge() - this.getAge();
    }
 /**
     * sorted()有两种 一种是不含参数的,另外一种是含有参数的
     *
     */
    @Test
    public void test06(){
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted()
                .forEach(author -> System.out.println(author.getName()));

    }
    @Test
    public void test07(){
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted(new Comparator<Author>() {
                    @Override
                    public int compare(Author o1, Author o2) {
                        return 0;
                    }
                })
                .forEach(author -> System.out.println(author));
    }

limit限制流的长度

    @Test
    public void test08(){
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted((o1,o2)->o1.getAge()-o2.getAge())
                // 限制流的长度  还是比较好用的
                .limit(3)
                .forEach(author -> System.out.println(author.getName()));
    }

skip(n)其中的n指的是跳过前n个元素

flatMap可以把一个对象转化成多个对象

@Test
    public void test09(){
        List<Author> authors = getAuthors();
        authors.stream()
                // 将List<Book> 转化为多个Book对象
                .flatMap(author -> author.getBookList().stream())
                .distinct()
                .forEach(book -> System.out.println(book.getName()));
    }

就是直接把一个对象转化为多个对象,这里可能有点不好理解

5.终结操作

注意一定要有终结的操作要不然不会出现效果的

forEach对流当中的元素进行遍历操作

count返回流当中元素的个数

    // count()返回的是long类型的
    @Test
    public void test11(){
        List<Author> authors = getAuthors();
        System.out.println(authors.stream()
                .distinct()
                .count());;
    }

max 和 min 选取最大数值和最小数值

    @Test
    public void test12(){
        List<Author> authors = getAuthors();
        System.out.println(authors.stream()
                .map(author -> author.getAge())
                .max(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        return o1-o2;
                    }
                }).get());
    }

collect将流转化为集合 List Map 和 Set

List 是有序集合,Set 和 Map 都是无序集合,List 集合的元素可以重复,Set 和 Map 的键不能重复,但是 Map 的值可以重复。值得注意的是,如果在 Map 中添加重复的键,那么该键对应的值会覆盖掉原来的值。


    /**
     * 将数据转化为set
     * @return
     */
    /**
     * 将数据转化为list
     * @return
     */
    @Test
    public void test13(){
        List<Author> authors = getAuthors();
        // stream流 转化为 List 集合
        List<Author> collect = authors.stream()
                .collect(Collectors.toList());
        // stream流 转化为 Set集合
        Set<Author> collect1 = authors.stream()
                .collect(Collectors.toSet());
    }

将流转化为map

  /**
     * 将流转化为map
     * @return
     */
    public void test14(){
        List<Author> authors = getAuthors();
        Map<String, List<Book>> collect = authors.stream()
                .collect(Collectors.toMap(author -> author.getName(), author -> author.getBookList()));
    }

查找和匹配

anyMatch查找是否含有匹配的元素,如果含有匹配的元素返回true 没有匹配的元素返回false

@Test
    public void test15(){
        List<Author> authors = getAuthors();
        boolean b = authors.stream()
                // 任意返回条件 任意的元素符合条件就会返回true
                // 没有符合条件的就会返回false
                .anyMatch(author -> author.getAge() < 13);
        System.out.println(b);
    }

allMatch所有的元素都匹配的话,才会返回true else 返回 false

    @Test
    public void test16(){
        List<Author> authors = getAuthors();
        System.out.println(authors.stream()
                .allMatch(author->author.getAge()<13));
    }

查找:

findAny 获取流当中的元素 该方法没有办法保证一定是流当中的第一个元素

findFirst 获取流当中的第一个元素

reduce归并缩减操作 对流当中的数据按照你指定的方式计算出来一个结果

reduce+map来进行简化映射

    @Test
    public void test17(){
        List<Author> authors = getAuthors();
        System.out.println(authors.stream()
                .map(author -> author.getAge())
                // 第一个元素的值是 传入的0
                .reduce(0, (sum, elment) -> sum + elment));
        
    }

reduce+map来求取年龄的最大值

    @Test
    public void test18(){
        List<Author> authors = getAuthors();
        System.out.println(authors.stream()
                .map(author -> author.getAge())
                .reduce(Integer.MIN_VALUE, (min, element) -> element > min ? element : min));
    }

流的特点:

惰性求值(如果没有终结操作,只有中间操作是不会去执行的)

流是一次性的

不会影响原始数据

6.optional

解决空指针异常,之前都是做个非空的判断

创建optional对象

Optional.ofNullable()方法 可以搞去空指针异常

 @Test
    public void test19(){
        List<Author> authors = getAuthors();
        for (Author author :authors){
            //创建optional对象
            Optional<Author> author1 = Optional.ofNullable(author);
            // 通过consumer来摆除空指针异常
            author1.ifPresent(author2 -> System.out.println(author2.getName()));
        }
    }

optional.of()方法不推荐使用

optional.get()碰到空的值还是会抛出空指针异常

所以推荐使用orElseGet()当碰到null的时候,会指出默认的数值

    @Test
    public void test21(){
        // orElseGet方法的使用
        Author newAut = null;
        Author author1 = new Author(1L, "杨杰炜", "my introduction 1", 18, null);
        System.out.println(Optional.ofNullable(newAut)
                .orElseGet(() -> new Author(2L, "wsy", "my introduction 2", 19, null)).getName());
    }

使用filter可以进行数据的过滤:


isPresent可以用来判断是否存在optional对象

ifPresent(new Consumer(){}如果存在的话则

optional同样存在map的方法可以进行数据的转换

常用的就是ofNullable+ifPresent()方法来进行

7.函数式接口

是否含有一个方法来判断是否是函数式接口

一般函数式接口会有@FunctionalInterface的注解

常见的函数式接口有:

consumer消费接口 比如在其中进行打印

Public interface consumer{
	void accept();
}

function计算转换接口

Public interface Function{
	R apply(T t);
}

predicate判断型接口 进行判断的

public interface Predicate<T>{
boolean test(T t);
}

supplier生产型接口 生产出需要的对象 把想要的对象生产之后拿过来

public imterface Supplier<T>{
	T get();
}

and方法的使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8LWvhG0u-1665623177851)(C:\Users\王率宇\AppData\Roaming\Typora\typora-user-images\image-20221013083004493.png)]

方法引用

如果方法体当中只有一个方法的调用的时候,可以使用方法引用

格式

类名这个强调的是全部的参数

类名::方法名

在这里插入图片描述

对象名::方法名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0uzBoiZ-1665623177853)(C:\Users\王率宇\AppData\Roaming\Typora\typora-user-images\image-20221013084036002.png)]

mapToInt int类型相比包装类的Integer来说有更大的效率

基本数据类型的优化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VrvSMHhi-1665623177854)(C:\Users\王率宇\AppData\Roaming\Typora\typora-user-images\image-20221013085151892.png)]

并行流:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fcEUgFAl-1665623177854)(C:\Users\王率宇\AppData\Roaming\Typora\typora-user-images\image-20221013085751427.png)]

peek是用来断点调试的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ie8cKuQh-1665623177855)(C:\Users\王率宇\AppData\Roaming\Typora\typora-user-images\image-20221013085940182.png)]

parallel可以把串行流转化为并行流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值