第四节:函数式编程

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())
                )
        );
posted @ 2021-05-28 19:26  位永光  阅读(89)  评论(0编辑  收藏  举报