1. 内容简述
Java版本,JDK 8
1.1 内置函数式接口
内置的函数式接口都在 java.util.function
包下
Function
表示一个函数(方法),接收一个单一的参数并返回一个单一的值
Predicate
表示一个简单的函数,接收一个值作为参数,返回真或假
UnaryOperator
代表一个操作,接收一个参数,并返回一个相同类型的参数
BinaryOperator
代表一个接收两个参数,并返回一个值的操作
Supplier
代表一个函数,提供某种类型的值
Consumer
代表一个函数,接收一个参数而不返回任何值
1.2 函数的组合
and/or
拼接两个函数
Predicate<String> startWithA = (text) -> text.startsWith("A");
Predicate<String> endWithX = (text) -> text.endsWith("X");
// 判断是否A开头并且X结尾
Predicate<String> WithAandX = startWithA.and(endWithX);
// 判断是否A开头或者X结尾
Predicate<String> WithAandX = startWithA.or(endWithX);
compose/andthen
函数执行顺序
Function<Integer, Integer> A = (value) -> value + 1;
Function<Integer, Integer> B = (value) -> value * 2;
// 先执行 B 在执行 A
Function<Integer, Integer> then = A.compose(B);
System.out.println(then.apply(2));
// 先执行 A 在执行 B
Function<Integer, Integer> then = A.andthen(B);
System.out.println(then.apply(2));
2. 基础阶段
2.1 创建数据流
数组创建
public static void main(String[] args) {
User[] array = new User[]{
new User(1, "李白"),
new User(2, "白起"),
new User(3, "赵云"),
new User(4, "韩信")
};
List<User> list = Arrays.stream(array)
.filter(u -> u.getId() > 2)
.limit(2)
.collect(Collectors.toList());
list.forEach(u-> System.out.println(u.getName()));
}
列表集合创建
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(1, "李白"));
list.add(new User(2, "白起"));
list.add(new User(3, "赵云"));
list.add(new User(4, "韩信"));
List<User> users = list.stream()
.filter(u -> u.getId() > 2)
.limit(2)
.collect(Collectors.toList());
users.forEach(u -> System.out.println(u.getName()));
}
2.2 流操作符
连接类型操作符,可跟其它操作符,不会中断流
筛选元素:
List<User> list = new ArrayList<>();
List<User> users = list.stream()
.filter(u -> u.getId() > 2)
.collect(Collectors.toList());
users.forEach(u -> System.out.println(u.getName()));
返回第一个元素:
List<User> list = new ArrayList<>();
Optional<User> first = users.stream().findFirst();
User user = first.get();
System.out.println(user.getName());
映射指定类型元素:
List<User> list = new ArrayList<>();
Set<String> collect = list.stream().map(x -> x.getName()).collect(Collectors.toSet());
System.out.println(collect.size());
终止操作符,后面不可跟其它操作符,中断流
是否有所有元素满足条件:
List<User> list = new ArrayList<>();
boolean match = list.stream().noneMatch(x -> x.getId() > 4);
System.out.println(match);
是否有一个满足条件:
List<User> list = new ArrayList<>();
boolean match = list.stream().anyMatch(x -> x.getId() > 2);
System.out.println(match);
是否全部不满足条件:有满足的为 false
List<User> list = new ArrayList<>();
boolean match = list.stream().noneMatch(x -> x.getId() > 4);
System.out.println(match);
数据总数:
List<User> list = new ArrayList<>();
long count = list.stream().count();
System.out.println(count);
最大,最小:
List<User> list = new ArrayList<>();
Optional<User> max = list.stream().max(Comparator.comparing(User::getId));
System.out.println(max.get().getId());
Optional<User> min = list.stream().min(Comparator.comparing(User::getId));
System.out.println(min.get().getId());
2.3 Optional
流
判断操作符
判断值是否存在,存在返回 true:
Optional<User> first = list.stream().findFirst();
first.isPresent();
处理空值
当值存在则返回值,不存在返回参数默认值:
List<User> list = new ArrayList<>();
Optional<User> first = list.stream().filter(x -> x.getId() > 1).findFirst();
User def = new User(5, "王战军");
User user = first.orElse(def);
System.out.println(user.getName());
当值存在则返回值,不存在返回方法的返回值:
List<User> list = new ArrayList<>();
Optional<User> first = list.stream().filter(x -> x.getId() > 1).findFirst();
User def = new User(5, "王战军");
User user = first.orElseGet(() -> def);
System.out.println(user.getName());
有值时处理
返回值,不存在抛出异常:
Optional<User> first = list.stream().filter(x->x.getId()>8).findFirst();
System.out.println(first.get());
当有值时,执行一个方法,方法参数为当前值:
List<User> list = new ArrayList<>();
Optional<User> first = list.stream().filter(x -> x.getId() > 1).findFirst();
first.ifPresent(x -> System.out.println(x.getName()));
2.4 Collectors
收集器
将流输出收集为一个集合对象
示例一:toSet
List<User> list = new ArrayList<>();
Set<String> collect = list.stream().map(x -> x.getName()).collect(Collectors.toSet());
System.out.println(collect.size());
示例二:toMap
使用一:输出KEY:VALUE
形式
List<User> list = new ArrayList<>();
Map<Integer, User> map = list.stream().collect(Collectors.toMap(
u -> u.getId(),
u -> u
));
System.out.println(userMap.size());
使用二:输出KEY:VALUE
形式,重复key将会选中其中一个值
List<User> list = new ArrayList<>();
Map<Integer, String> map = list.stream().collect(Collectors.toMap(
u -> u.getId(),
u -> u.getName(),
(oldvalue, newvalue) -> oldvalue
));
System.out.println(map.size());
使用三:输出KEY:VALUE
形式,重复key将会选中其中一个值,并按 KEY 值排序
List<User> list = new ArrayList<>();
Map<Integer, String> map = list.stream().collect(Collectors.toMap(
u -> u.getId(),
u -> u.getName(),
(oldvalue, newvalue) -> oldvalue,
()->new TreeMap<>() // TreeMap::new
));
System.out.println(map.size());
示例三:toCollection
自定义规则
使用一:使用自定义排序器
List<User> list = new ArrayList<>();
Comparator<User> byAge = Comparator.comparing(User::getId);
TreeSet<User> collect = list.stream()
.collect(Collectors.toCollection(() -> new TreeSet<>(byAge)));
System.out.println(collect.size());
聚合函数
平均值:
List<User> list = new ArrayList<>();
Double aDouble = list.stream().collect(Collectors.averagingInt(u -> u.getId()));
System.out.println(aDouble);
总和:
List<User> list = new ArrayList<>();
Integer sum = list.stream().collect(Collectors.summingInt(u -> u.getId()));
System.out.println(sum);
多个聚合值:
List<User> list = new ArrayList<>();
DoubleSummaryStatistics collect = list.stream()
.collect(Collectors.summarizingDouble(u -> u.getId()));
System.out.println("和:" + collect.getSum());
System.out.println("MAX:" + collect.getMax());
System.out.println("MIN:" + collect.getMin());
System.out.println("平均:" + collect.getAverage());
System.out.println("行数:" + collect.getCount());
分组统计
使用一:简单分组,单个字段
List<User> list = new ArrayList<>();
Map<Integer, List<User>> map = list.stream()
.collect(Collectors.groupingBy(u -> u.getId()));
System.out.println(map.size());
使用二:对分组后数据进行聚合
List<User> list = new ArrayList<>();
Map<Integer, DoubleSummaryStatistics> map = list.stream()
.collect(Collectors.groupingBy(
u -> u.getId(),
Collectors.summarizingDouble(u -> u.getId())
)
);