Optional(创建、过滤、判断、数据转换)、函数式接口、方法引用(由浅入深的函数式编程③)

前文

Optional 对很多人来说还是比较陌生的一个东西,但在stream流里面其实已经出现过很多次了
stream流里的Optional实例可以看一下笔者上一篇文:工作中都爱用的Stream流,多实例详解过滤、匹配、归并等超完整笔记~(由浅入深的函数式编程②)

概述

使用Optional主要是为了避免空指针异常

使用Optional

创建对象

一般使用Optional的静态方法ofNullable来把数据封装成一个Optional对象。

User user = getUser();
Optional<User> userOptional = Optional.ofNullable(user);
//即使getUser()方法返回的是null,也不会报空指针异常
userOptional.ifPresent(user -> System.out.println(user.getName()));

但其实更简便且持久生效的便是将getUser()方法的返回对象改为Optional:

public static Optional<User> getUser(){
	User user = new User();
	xxxx//直接加user对象内容
	return Optional.ofNullable(user);
}

note:从数据库取内容则dao方法改为返回Optional对象。
修改后则直接:

Optional<User> userOptional = getUser();
userOptional.ifPresent(user -> System.out.println(user.getName()));

安全消费值

获取到Optional对象后需要消费数据,可以使用 ifPresent() 方法,此方法会先行判断封装数据是否为空,不为空时才会继续执行具体的消费代码。
这样消费就更安全。
(上述实例已经使用过了)

安全获取值

可以直接get(),但是并不安全,如果为空则会返回空指针。

orElseGet

先判空,不为空则能获取,如果为空则根据传入的参数来创建对象作为默认值返回。

Optional<User> userOptional = getUser();
User user = userOptional.orElseGet(() -> new User);
System.out.println(user.getName());

orElseThrow

先判空,不为空则能获取,如果为空则根据传入参数创建异常抛出。

Optional<User> userOptional = Optional.ofNullable(getUser());
try{
	User user = userOptional.orElseThrow(Supplier<Throwable> () -> new RuntimeException("user为空"));
	System.out.println(user.getName());
}catch (Throwable throwable){
	throwable.printStackTrace();
}

过滤

当符合条件时,则会返回需求数据;不符合条件则会被过滤掉,返回一个新的Optional对象,此对象为null.

Optional<User> userOptional = getUserOptional(); 
Optional<User> optional =  userOptional.filter(user -> user.getAge() > 18)
								.ifPresent(user -> System.out.println(user.getName()));

判断

布尔类型的isPresent()

Optional<User> userOptional = getUserOptional();
if(userOptional.isPresent()){
//已经判空后则可以使用get()
	System.out.println(userOptional.get().getName());
}

数据转换

和stream流的map很类似,可以转换数据为Optional对象。
如果进入空置也不会报空指针。

Optional<User> userOptional = getUserOptional();
userOptional.map(user -> user.getEquipments())
			.ifPresent(equipments -> System.out.println(equipments));

==================================================
Optional的基本和常用的知识如上所示。
接下来是关于函数式接口的内容。

函数式接口

概述

函数接口:只有一个抽象方法的接口
stream流一直在使用函数接口。
JDK的函数式接口一般会加一个注解:@FunctionalInterface

常见函数式接口

不需要记住,底层在使用,了解熟练即可。

  • Consumer消费接口
    可以在方法中对传入的参数进行消费。

  • Function计算转换接口
    根据接口里的抽象方法的参数列表和返回值类型,在方法里对传入的参数进行计算或转换,然后返回结果。

  • Predicate判断接口
    根据接口里的抽象方法的参数列表和返回值类型,在方法里判断参数条件,返回判断结果。

  • Supplier生产型接口
    根据接口里的抽象方法的参数列表和返回值类型,在方法里创建对象,返回创建对象。

常用默认方法

  • and/or
    可以拼接条件等
    stream流里用Lambda表达式时注意将and改为&&,or改为||
    实例:
//打印年龄和姓名长度同时符合条件的用户
List<User> users = getUsers();
users.stream()
	 .filter(user -> user.getAge()>17 && user.getName().length()>1)
	 .forEach(user -> System.out.println(user.getAge()+"+"+user.getName()));
  • negate
    相当于在判断前加" !",取反。
    实例:
//筛选姓名长度不大于2的用户
List<User> users = getUsers();
users.stream()
	 .filter(user -> user.getName().length()>2)
	 .negate()

方法引用

概述

进一步简化Lambda的方式。

使用场景

方法体只有一个引用方法的情况
实例:

List<User> users = getUsers();
users.stream()
	 //一个方法的情况
	 .map(user->user.getAge())
	 //就可以改成方法引用
	 .map(user::getAge)

基本格式

由上实例可总结:

类名/对象名::方法名

构造器引用

概述

方法体内的一行代码是构造器则可以使用构造器引用

格式

类名::new

以上都可以使用idea直接优化,不需要特意记住。

===================================================================
关于函数式编程就暂时更新到这里啦,工作中实际使用和看懂代码基本已经没有大问题了。码字不易,希望大家多多支持小soul呀!😃

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值