Java1.8新特性Optional和stream流操作的用法,为什么要用这些?
Optional和stream流操作都属于1.8的函数式编程的经典实现,在我们结合着Optional和stream操作集合,可以使我们更快的适应lambda表达式
Optional
Optional类常用方法
先看下Optional常用方法简介:
图片来源:JDK1.8新特性值Optional,详细的方法demo这个链接里面也有,刚刚接触这个类的朋友可以学一下。
为什么要用Optional?
一方面是为了使我们代码的简洁、明晰,不会过于臃肿,另一方面1.8为我们提供了更好的判断空指针的方式,是很值得我们在日常开发使用的,举个简单的例子,发现下Optional的妙处:
场景:下单时,判断一个用户地址是浙江杭州才可以下单:
代码:
// 代码1
Person person1 = getPersonByMobile("18888888888");
if (null != person1) {
String address = person1.getAddress();
if (null != address) {
if (address.contains("浙江杭州")) {
// 执行下单
}
} else {
throw new CustomRunTimeException("不可下单");
}
} else {
throw new CustomRunTimeException("不可下单");
}
// 代码2
Person person1 = getPersonByMobile("18888888888");
boolean flag = false;
if (null != person1) {
String address = person1.getAddress();
if (null != address) {
if (address.contains("浙江杭州")) {
flag = true;
}
}
}
if(!flag){
throw new CustomRunTimeException("不可下单");
}
// 执行下单
代码2在代码明晰上要好很多,可是代码的非空判断还是很多,过于冗余,这时我们就可以使用Optional来处理(好处多多,大家自己体会哈)
String address = Optional.ofNullable(getPersonByMobile("18888888888"))
.map(person2 -> person2.getAddress())
.filter(s -> s.contains("浙江杭州"))
.orElseThrow(() -> new CustomRunTimeException("不可下单"));
// 执行下单
就是这么简单的代码,就实现了和上面较为臃肿的代码同样的功能,而且Optional支持链式调用十分强大
上面optional代码使用的逻辑和大家简单说下,getPersonByMobile(“18888888888”)返回person对象①,
不为null,通过map()方法得到用户的地址数据②,不为null通过filter()判断字符串是否符合过滤条件③,符合,返回字符串给address,期间①②③有一处为null,都会抛出orElseThrow里面的异常。
stream()
stream常用方式
stream()提供了对集合的强大操作方式,如果想深入了解可以参考这篇文章java8 stream常用方法
常见操作
对stream()的各种方法也没一定要具体掌握,主要是在经常使用的操作集合的场景可以灵活运行即可。
下面给出来本人在工作中常见的操作集合的方式,感兴趣的可以拿来练手(由易到难)
// 1、遍历
// 2、 过滤不需要的数据
// 3、按照某个属性排序
// 3.1生成VO类
// 4、得到手机号list,并排序
// 5、是否存在13588438646手机号的用户
// 6、根据手机号组成map
// 7、判断符合条件的数据量
// 8、根据userId组成map,根据key保存的userId可排序
下面是通过stream()来实现
package com.fss.controller.stream;
import com.fss.controller.model.Person;
import com.fss.controller.vo.PersonVO;
import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
public class StreamUseTest {
private static Logger logger = LoggerFactory.getLogger(StreamUseTest.class);
private static List<Person> personList = new ArrayList<>();
static {
personList.add(new Person("hsf", "13583452646", 18, "广州"));
personList.add(new Person("gkd", "18685642548", 20, "北京"));
personList.add(new Person("nha", "15545643423", 16, "上海"));
}
@Test
public void test1() {
// 1、遍历
personList.forEach(person -> {
System.err.println(person.toString());
});
// 2、过滤不需要的数据
List<Person> filterList = personList.stream().filter(person -> person.getMobile().contains("155456")).collect(Collectors.toList());
System.err.println(filterList.toString());
// 3、按照某个属性排序(2、3有时会需要一起使用,过滤并排序)
List<Person> sortedList = personList.stream().sorted((o1, o2) -> -(o1.getAge() - o2.getAge())).collect(Collectors.toList());
System.err.println(sortedList.toString());
// 3.1、生成VO类
List<PersonVO> personVOList = personList.stream().map(person -> {
return PersonVO.builder().personId(person.getPersonId()).name(person.getName()).build();
}).collect(Collectors.toList());
System.err.println(personVOList);
// 4、得到手机号list,并排序
List<String> mobileList = personList.stream().map(person -> person.getMobile()).collect(Collectors.toList()).stream().sorted((o1, o2) -> -o1.compareTo(o2)).collect(Collectors.toList());
System.err.println(mobileList.toString());
// 5、是否存在13588438646手机号的用户
boolean b = personList.stream().anyMatch(person -> person.getMobile().contains("15545643423"));
System.err.println("是否存在15545643423手机号的用户:" + b);
// 6、根据手机号组成map
Map<String, Person> personMap = personList.stream().collect(Collectors.toMap(Person::getMobile, person -> person));
System.err.println(personMap);
// 7、判断符合条件的数据量
long count = personList.stream().filter(person -> person.getMobile().contains("15545643423")).count();
System.err.println(count);
// 8、根据userId组成map,id可排序
Map<Long, PersonVO> personVOMap = personList.stream().collect(Collectors.toMap(Person::getPersonId, person -> PersonVO.builder()
.personId(person.getPersonId()).address(person.getAddress()).name(person.getName())
.age(person.getAge()).mobile(person.getMobile()).idCard("34120xxxxxx").build()
));
Map<Long, PersonVO> map = new LinkedHashMap<>();
personVOMap.entrySet().stream().sorted(Map.Entry.<Long, PersonVO>comparingByKey().reversed()).
forEachOrdered(longPersonVOEntry -> {
map.put(longPersonVOEntry.getKey(), longPersonVOEntry.getValue());
});
System.err.println(map);
}
}