函数式编程

函数式编程

Lambda表达式

格式:只关注方法参数与方法体

1
(参数列表) -> {代码}

省略规则:

  • 参数类型可以省略
  • 方法体只有一句代码,大括号return和唯一一句代码的分号可以省略
  • 方法只有一个参数时,小括号可以省略

创建流

单列集合:集合对象.stream()

数组:Arrays.stream(数组)或者使用Stream.of()

双列集合:转换成单列集合再创建

1
2
Map<String,Integer> map = new HashMap<>();
Stream<Map.Entry<String,Integer>> stream = map.entrySet().stream();

中间操作

filter() 过滤

map() 类型转换或计算

image-20220331232607054

distinct() 去重,去重的依据是Object的equals方法

sorted() 排序

limit() 限制流中元素的长度

skip() 跳过

flatMap() 将一个元素转换为多个元素,即目标类型仍然是Stream

终结操作

forEach() 遍历

count() 统计数量

max&min 最大值 最小值

collect() 将流中的元素转换为集合

  • 转换为List: collect(Collectors.toList());
  • 转换为Set: collect(Collectors.toSet());
  • 转换为Map: collect(Collectors.toMap());其中参数时两个Function,即key和value的转换规则

anyMatch: 任意一个匹配到就返回TRUE

allMatch: 所有的都匹配则返回TRUE

noneMatch: 都不匹配返回TRUE

findAny: 获取任意一个元素,随机匹配

findFirst: 查找流中的第一个元素

reduce(): 将Stream中的元素归并为一个结果,思想来源于Google的MapReduce

Stream流的特性

  • 惰性求值
  • 不能重复使用同一个流对象
  • 不会影响原数据
  • 短路

Optional

创建对象
1
2
3
4
5
//实际使用过程中,不会这样操作,而是将方法返回值定义为Optional对象,直接拿过来用Optional对象就可以了	
Optional<User> user = Optional.ofNullable(user);
//of方法会出现空指针,不建议使用
Optional<User> user = Optional.of(user);
//注:在mybatis3.5中返回的对象就已经被封装成Optional对象了
安全消费
1
user.ifPresent(u -> System.out.println(user));
安全获取值
1
2
3
4
5
6
7
//get()不推荐使用,不存在值会抛出NoSuchElementException
user.get();
//如果不存在返回一个默认值
user.orElseGet(()->new User());
//用于统一异常处理
user.orElseThrow(()->new BusinessException("空对象"));

安全过滤
1
2
//过滤姓名长度大于10的进行输出
user.filter(u->u.getName().length()>10).ifPresent(u -> System.out.println(user));
数据转换
1
user.map(u -> u.getPets()).isPresent(pets -> System.out.println(pets));

方法引用

格式

类名或对象名::方法名

基本数据类型的优化

直接使用mapToInt, matToLong,flatMatToInt等,将数据转换为基本数据类型,尽量避免在流操作的过程中频繁的自动拆箱和装箱

并行流

线程安全

使用:

通过调用Stream对象的parallel方法转换为并行流

或者直接对集合对象调用parallelStream方法直接获取并行流

Tips

当需要对流进行断点调试时,可以在任意中间操作中直接调用peek方法,进行调试


函数式编程
http://example.com/2023/03/09/Java/CleanCode/函数式编程/
作者
UncleBryan
发布于
2023年3月9日
许可协议