自学内容网 自学内容网

java8函数式编程学习(二):optional,函数式接口和并行流的学习

简介

java8函数式编程中optional的简单使用,函数式接口的了解,并行流的使用。

optional

可以更优雅的来避免空指针异常。类似于包装类,把具体的数据封装到optional对象内部,然后使用optional的方法去操作封装好的数据。

创建optional对象

ofNullable方法

使用静态方法ofNullable把数据封装成optional对象,方法的参数可为空。
通常会用在方法上,把方法的返回值封装成optional对象返回。

public class OptionalTest01 {
    public static void main(String[] args) {
        Optional<Integer> num = getNum();
        num.ifPresent(num1-> System.out.println(num1));
    }
    public static Optional<Integer> getNum(){
        Integer a= 2;
        return Optional.ofNullable(a);
    }
}

当a=null时,则不会输出任何东西,但也不会报空指针异常。

扩展:

mybatis3.5以上是支持optional类型的,可以直接把dao层的返回值定义为optional,mybatis会自动的把数据封装成optional对象返回。

of方法

使用optional的静态方法of来封装optional对象,参数不能为null,否则会报空指针异常。

package com;

import java.util.Optional;

public class OptionalTest02 {
    public static void main(String[] args) {
        Optional<Integer> num = getNum();
        num.ifPresent(num1-> System.out.println(num1));
    }
    public static Optional<Integer> getNum(){
        Integer a= null;
        return Optional.of(a);
    }
}

在这里插入图片描述

empty方法

empty可以把null封装成optional对象,可以和of方法一起使用。

package com;

import java.util.Optional;

public class OptionalTest03 {
    public static void main(String[] args) {
        Optional<Integer> num = getNum();
        num.ifPresent(num1-> System.out.println(num1));
    }
    public static Optional<Integer> getNum(){
        Integer a= null;
        return a==null?Optional.empty():Optional.of(a);
    }
}

所以,还是ofNullable方法用的比较多,empty和of方法比较少用。

判断

ifPresent

会判断封装的数据是否为空,不为空时才会执行具体的操作,可以安全的消费值

isPresent

会判断封装的数据是否为空,为空返回false,不为空返回true。

package com;

import java.util.Optional;

public class OptionalTest07 {
    public static void main(String[] args) {
        Optional<Integer> num = getNum();
        if(num.isPresent()){
            System.out.println(num.get());
        }
        else
        {
            System.out.println("value is null");
        }

    }
    public static Optional<Integer> getNum(){
        Integer a= null;
        return Optional.ofNullable(a);
    }
}

安全的获取值

orElseGet

安全的获取值,如果optional对象没有值,则返回设置的值,如果有值,则获得值。

package com;

import java.util.Optional;

public class OptionalTest04 {
    public static void main(String[] args) {
        Optional<Integer> num = getNum();
        Integer integer = num.orElseGet(() -> 2);
        System.out.println(integer);
    }
    public static Optional<Integer> getNum(){
        Integer a= null;
        return Optional.ofNullable(a);
    }
}

在这里插入图片描述

orElseThrow

获取数据的时候,如果值为空,那么会抛出指定的异常。方便springboot的统一异常的处理。

package com;

import java.util.Optional;

public class OptionalTest05 {
    public static void main(String[] args) {
        Optional<Integer> num = getNum();
        try {
            Integer integer = num.orElseThrow(() -> new RuntimeException("value is null"));
            System.out.println(integer);
        }catch (Throwable e){
            e.printStackTrace();
        }
    }
    public static Optional<Integer> getNum(){
        Integer a= null;
        return Optional.ofNullable(a);
    }
}

过滤

可以使用filter方法进行过滤,如果都不符合过滤条件,optional还是会变成一个null的对象。

package com;

import java.util.Optional;

public class OptionalTest06 {
    public static void main(String[] args) {
        Optional<Integer> num = getNum();
        Optional<Integer> integer = num.filter(a -> a > 5);
        integer.ifPresent(b-> System.out.println(b));
    }
    public static Optional<Integer> getNum(){
        Integer a= 2;
        return Optional.ofNullable(a);
    }
}

在这里插入图片描述

函数式接口

只有一个抽象方法的接口就是函数式接口,函数式接口可以用注解@FunctionalInterface修饰,也可以没有这个注解

常见的函数式接口

  • consumer:消费接口,可以对传入方法的参数做操作,没有返回值
  • function:计算转换接口,可以对传入方法的参数做计算或转换,有返回值
  • predictate:判断接口,可以对传入方法的参数条件判断,返回boolean
  • supplier:可以在方法中创建对象并返回。

方法引用

使用lambada表达式的时候,如果方法体只有一个方法的调用,可以使用方法引用进一步简化代码。
这个其实是作为了解的,没有必要为了简化而简化。遇到这种写法的时候知道就好了

格式

引用类的静态方法时:类名:: 方法名
引用对象的实例方法时:对象名:: 方法名
构造器引用:类名::new

num.ifPresent(num1-> System.out.println(num1));可以改成num.ifPresent(System.out::println);
在lambada式上,alt+回车,如果有图中的选项,则可以使用方法引用的方式简化代码。
在这里插入图片描述

stream流的优化

基本数据类型优化

很多的stream流中的方法,都是使用了泛型的,所以涉及到的参数和返回值都是引用数据类型。在方法中,会有很多的装箱拆箱的操作,会损耗性能,比如authors.stream().map(author -> author.getAge());这个代码中,传入的参数a是Integer的,在比较的时候,会拆箱为int,然后结果又要装箱成integer。
常用的优化方法:

  • mapToInt
  • mapToLong
  • mapToDouble
  • flatToDouble
  • flatToInt

并行流

stream流中有大量的数据时,可以使用并行流去提高效率,它会把任务分配给多个线程去操作。它不需要我们手动去实现复杂的多线程编程,而是直接调用parallel方法或者通过parallelStream直接获取并行流对象

parallel方法

package com;

import java.util.stream.Stream;

public class StreamTest6 {
    public static void main(String[] args) {
        Integer[] arr =  {1,1,2,2,3,3,4,4,5,6};
        Stream.of(arr)
                .parallel()
                .peek(n-> System.out.println(n+Thread.currentThread().getName()))
                .distinct()
                .forEach(arr3-> System.out.println(arr3));
    }
}

解析:
这个peek方法是stream流中的调试线程方法
在这里插入图片描述
如果不是用parallel方法,输出结果是:
在这里插入图片描述
可以看到是只有一个线程的。

parallelStream方法

package com;

import java.util.ArrayList;
import java.util.List;

public class StreamTest4 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.parallelStream()
                .peek(n-> System.out.println(n+Thread.currentThread().getName()))
                .forEach(i-> System.out.println(i));
    }
}


原文地址:https://blog.csdn.net/weixin_45037073/article/details/140667817

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!