Java 函数式编程
Java 函数式接口
有且仅有一个未实现的非静态方法的接口叫做“函数式接口”
interface IFactory {
T create();
}
建立流的几种方式
- Arrays.stream(arraysName)
- Collection.stream()(即所有 Collection 的实现类:list.stream()、set.stream())
- Stream.of(将一个一个元素放入流中,可以放入任意类型对象)
Stream.of(arrays[1], 2, "string")
- Stream.iterate()(流迭代器)
//初始值为 0,执行 +1 操作
Stream.iterate(0, n -> n + 1).limit(10)
- Stream.generate()(构造流)
//流中构造 10 个随机数
Stream.generate(() -> Math.random()).limit(10)
常见操作符
- 中间操作符
filter:元素过滤
map:从一种对象映射成另一种对象
List userDTO = userList.stream()
.map(user -> UserDTO.builder()
.name(user.getName())
.mobile(user.getMobile())
.build()
)
.collect(Collectors.toList());
peek:对元素的属性进行操作,常用于debug展示流过程输出
.peek(user -> log.debug("user {}", user))
findAny:在 parallelStream() 中使用,寻找满足条件的任一元素
findFirst:寻找满足条件的第一个元素
- 终端操作符(后面不能再跟其他函数)
forEach:循环操作
forEachOrdered:在 parallelStream() 中使用该函数控制元素操作顺序
anyMatch:任一匹配上就返回 true
noneMatch:没有匹配上就返回 true
allMatch:所有元素匹配上才返回 true
collect:将流元素收集到一个集合中,Collectors 配合使用
Map userMap = userList.stream()
.collect(Collectors.toMap(User::getId, user -> user));
- 具有统计意义的终端操作符
count:统计数量
min
max
Optional 流
核心作用:进行流处理时,比如 filter 过滤之后可能没有符合条件的元素,流已经为 NULL,这种情况下就可以使用 Optional 流作为返回对象,保证后续流操作能正常执行,不报错。
常用方法
isPresent():如果不为空返回 true
isEmpty():如果为空返回 true
get():如果 Optional 有值则将其返回,否则抛异常
以下三个方法可以用来 Optional 转 List,如:
.ifPresent(Collections.toList())
orElse():当 Optional 为空,可以给定一个默认值,
ifPresent():当流不为空时,执行该函数里的代码块,如
ifPresentOrElse(a -> {a++}, () -> {log.debug("空")}):当流不为空时,执行前面的代码块,为空时执行后面的代码块
Collectors-收集器
toSet()
toMap()
Map userMap = userList.stream()
.collect(Collectors.toMap(User::getId, user -> user));
toList()
toCollection()
聚合函数
averagingDouble():求平均值
summingInt():求和
summarizingDouble():DoubleSummaryStatistics 配合使用,可对其进行各种聚合操作(getAverage()、getCount()、getMax()、getMin()、getSum())
double avg = userList.stream().collect(Collectors.averagingDouble(User::getAge));
DoubleSummaryStatistics stat = userList.stream().collect(Collectors.summarizingDouble(User::getAge));
double avg = stat.getAverage();
Long count = stat.getCount();
groupingBy(groupCondition, mapValue):分组
//按年龄分组
Map> groupUser = userList.stream().collect(Collectors.groupingBy(user -> (int)Math.floor(user.getAge() / 10)));
//统计不同年龄阶段的各聚合值
Map groupUser = userList.stream().collect(Collectors.groupingBy(user -> (int)Math.floor(user.getAge() / 10),
summarizingDouble(User::getAge)));
//分组映射
Map> result = userList.stream().collect(
Collectors.groupingBy(
user -> (int)Math.floor(user.getAge() / 10),
Collectors.mapping(
user -> new UserDto(
user.getId(), user.getUserName()
),
Collectors.toList()
)
)
);
mapping(value, 下游链或者Collectors.toList()等集合)
List strings = List.of("bb", "ddd", "cc", "a");
Map> result = strings.stream().collect(groupingBy(
String::length,
mapping(
String::toUpperCase,
filtering(
s -> s.length() > 1,
toCollection(TreeSet::new)
)
)
));
Collectors - 排序
sorted()
//默认对简单类型升序排列
List sort = list.stream().sorted().collect(toList());
//简单类型自定义排列
List sort = list.stream().sorted(
(a,b) -> a.compareTo(b))
.collect(toList());
//对简单类型降序排列
List sort = list.stream().sorted(
Comparator.reverseOrder())
.collect(toList());
//取对象中某个属性自定义排序
List sort = userList.stream().sorted(
Comparator.comparing(
user -> user.getId(),
(a, b) -> a.compareTo(b)
)
)
.collect(toList());
List sort = userList.stream().sorted(
(a, b) -> a.getUserName().compareTo(b.getUserName())
)
.collect(toList());
flatMap - 处理流的嵌套
父子对象常见的集合属性(如:List
List courseList = studentList.stream().flatMap(
student -> student.getCourseList().stream())
.collect(toList());
过滤Optional<>流中的空值对象,剩下的都是有值的Opitonal<>对象
.flatMap(Optional::stream)