0
点赞
收藏
分享

微信扫一扫

Lambda应用

朱小落 2021-10-15 阅读 51
技术分享

Java8中的流式处理,让集合操作变得简单,通常需要用多行代码才能完成的操作,而使用Lambda表达式处理可能仅需要一行代码即可实现。比如,如果我们对一个整数的集合,需要挑选出3的倍数,然后将其组装成一个集合返回。在Java8之前,需要这样做

public class Test {
    public static void main(String[] args) {
        // 初始化数据
        List<Integer> numList = new ArrayList<Integer>() {
            {
                add(1);
                add(2);
                add(3);
                add(4);
                add(5);
                add(6);
            }
        };
        // 最终返回的结果集合
        List<Integer> result = new ArrayList<>();
        // 筛选3的倍数
        for (Integer num : numList) {
            if (num % 3 == 0) {
                result.add(num);
            }
        }
        System.out.println(result);
    }
}

使用Lambda表达式处理,可以这么写

public class Test {
    public static void main(String[] args) {
        // 初始化数据
        List<Integer> numList = new ArrayList<Integer>() {
            {
                add(1);
                add(2);
                add(3);
                add(4);
                add(5);
                add(6);
            }
        };
        // 使用Lambda表达式处理
        List<Integer> result = numList.stream().filter(num -> num % 3 == 0).collect(Collectors.toList());
        System.out.println(result);
    }
}

JDK为Lambda表达式内置了非常丰富的函数式接口

函数式接口 描述符 原始类型
Predicate<T> T -> boolean IntPredicate, LongPredicate, DoublePredicate
Consumer<T> T -> void IntConsumer, LongConsumer, DoubleConsumer
Funcation<T, R> T -> R IntFuncation<R>, IntToDoubleFunction, IntToLongFunction<R>, LongFuncation…
Supplier<T> () -> T BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier
UnaryOperator<T> T -> T IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator
BinaryOperator<T> (T, T) -> T IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator
BiPredicate<L, R> (L, R) -> boolean
BiConsumer<T, U> (T, U) -> void
BiFunction<T, U, R> (T, U) -> R

Lambda表达式应用(代码示例)

数据初始化(数据准备)
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Data
public class Region {

    /*** id */
    private long id;

    /*** 地区*/
    private String regionName;

    /*** 编码 */
    private int code;

    /*** 等级 */
    private int level;

    /*** 专业 */
    private String major;

    /*** 学校 */
    private String school;
}
private static List<Region> regions = new ArrayList<Region>() {{
    add(new Region(20160001, "南京", 20, 1, "土木工程", "南京大学"));
    add(new Region(20160002, "苏州", 21, 2, "信息安全", "南京大学"));
    add(new Region(20160003, "无锡", 22, 3, "经济管理", "南京大学"));
    add(new Region(20160004, "常州", 21, 2, "信息安全", "南京大学"));
    add(new Region(20161001, "镇江", 21, 2, "机械与自动化", "江苏大学"));
    add(new Region(20161002, "南通", 23, 4, "土木工程", "江苏大学"));
    add(new Region(20161003, "扬州", 23, 4, "计算机科学", "江苏大学"));
    add(new Region(20162001, "泰州", 22, 3, "土木工程", "泰州学院"));
    add(new Region(20162002, "淮安", 23, 4, "计算机科学", "泰州学院"));
    add(new Region(20163001, "徐州", 24, 5, "土木工程", "中国矿业大学"));
}};
private static List<Integer> numbers = new ArrayList<Integer>() {{
    add(1);
    add(2);
    add(3);
    add(4);
    add(5);
    add(6);
    add(7);
    add(8);
}};
filter
// 筛选出所有南京大学的区域
List<Region> result = regions.stream()
        .filter(region -> "南京大学".equals(region.getSchool()))
        .collect(Collectors.toList());
distinct
// 筛选出所有不重复的偶数
List<Integer> result = numbers.stream()
        .filter(num -> num % 2 == 0)
        .distinct()
        .collect(Collectors.toList());
limit
// 筛选出南京大学的区域,取前两个
List<Region> result = regions.stream()
        .filter(region -> "南京大学".equals(region.getSchool()))
        .limit(2)
        .collect(Collectors.toList());
sorted
// 筛选出南京大学的区域,取前两个,并且按照等级排序
List<Region> result = regions.stream()
        .filter(region -> "南京大学".equals(region.getSchool()))
        .sorted(Comparator.comparingInt(Region::getLevel))
        .limit(2)
        .collect(Collectors.toList());
skip
// 筛选出南京大学的区域,并且按照等级排序,然后跳过前两条数据
List<Region> result = regions.stream()
        .filter(region -> "南京大学".equals(region.getSchool()))
        .sorted(Comparator.comparingInt(Region::getLevel))
        .skip(2)
        .collect(Collectors.toList());
map
// 筛选出所有专业为计算机科学的区域名称
List<String> result = regions.stream()
        .filter(region -> "计算机科学".equals(region.getMajor()))
        .map(Region::getRegionName)
        .collect(Collectors.toList());

// 筛选出所有专业为计算机科学的区域,并计算其code之和
int result = regions.stream()
        .filter(region -> "计算机科学".equals(region.getMajor()))
        .mapToInt(Region::getCode)
        .sum();
flatMap
String[] arr = {"java8", "is", "easy", "to", "use"};
// 输出构成这一数组的所有非重复字符
List<String[]> result = Arrays.stream(arr)
        .map(str -> str.split(""))
        .distinct()
        .collect(Collectors.toList());

List<String> result = Arrays.stream(arr)
        .map(str -> str.split(""))
        .flatMap(Arrays::stream)
        .distinct()
        .collect(Collectors.toList());
allMatch

检测是否全部都满足指定的参数行为。

// 检测所有区域等级都是大于5
boolean allMatch = regions.stream()
        .allMatch(region -> region.getLevel() > 5);
anyMatch

检测是否存在一个或多个满足指定的参数行为。

// 检测是否有南京大学的区域
boolean anyMatch = regions.stream()
        .anyMatch(region -> "南京大学".equals(region.getSchool()));
noneMatch

检测是否不存在满足指定行为的元素。

// 检测是否不存在专业为计算机科学的区域
boolean noneMatch = regions.stream()
        .noneMatch(region -> "计算机科学".equals(region.getMajor()));
findFirst

返回满足条件的第一个元素。

// 查找专业为土木工程且拍在第一的区域
Optional<Region> first = regions.stream()
        .filter(region -> "土木工程".equals(region.getMajor()))
        .findFirst();
findAny

findAny相对于findFirst的区别在于,findAny不一定返回第一个,而是返回任意一个。

// 查找专业为土木工程的任意一个区域
Optional<Region> any = regions.stream()
        .filter(region -> "土木工程".equals(region.getMajor()))
        .findAny();
归约

收集器提供了相应的归约操作,但是与reduce在内部实现上是有区别的,收集器更加适用于可变容器上的归约操作,这些收集器广义上均基于Collectors.reducing()实现。

// 区域总和
regions.stream().collect(Collectors.counting());
regions.stream().count();
// 区域编码的最大值和最小值
Optional<Region> maxResult = regions.stream()
        .collect(Collectors.maxBy((c1, c2) -> c1.getCode() - c2.getCode()));
Optional<Region> maxResult2 = regions.stream()
        .collect(Collectors.maxBy(Comparator.comparing(Region::getCode)));
Optional<Region> maxResult3 = regions.stream()
        .max(Comparator.comparing(Region::getCode));
Optional<Region> minResult = regions.stream()
        .min(Comparator.comparing(Region::getCode));
// 区域code之和
Integer sum = regions.stream()
        .collect(Collectors.summingInt(Region::getCode));
Integer sum2 = regions.stream()
        .mapToInt(Region::getCode)
        .sum();
// 区域平均等级
Double average = regions.stream()
        .collect(Collectors.averagingInt(Region::getLevel));
// 区域等级的最大值、最小值、平均值、总和、个数
IntSummaryStatistics statistics = regions.stream()
        .collect(Collectors.summarizingInt(Region::getLevel));
// 字符串拼接
String names = regions.stream()
        .map(Region::getRegionName)
        .collect(Collectors.joining());
String names2 = regions.stream()
        .map(Region::getRegionName)
        .collect(Collectors.joining(","));
分组
// 按照学校名称分组
Map<String, List<Region>> groups = regions.stream()
        .collect(Collectors.groupingBy(Region::getSchool));
// 多级分组
Map<String, Map<String, List<Region>>> groups2 = regions.stream()
        // 一级分组
        .collect(Collectors.groupingBy(Region::getSchool,
                // 二级分组
                Collectors.groupingBy(Region::getMajor)));
// 分组完后,统计每组个数
Map<String, Long> groupCount = regions.stream()
        .collect(Collectors.groupingBy(Region::getSchool,
                // 该参数不添加,会默认是Collectors.toList()
                Collectors.counting()));
分区

分区可以看做是分组的一种特殊情况,在分区中key只有两种情况,true或false,目的是将待分区集合按照条件一分为二,Java8的流式处理利用collectors.partitioningBy()方法实现分区,该方法接收一个谓词。

// 按照学校将区域分为有南京大学的,和没有南京大学的
Map<Boolean, List<Region>> partition = regions.stream()
        .collect(Collectors.partitioningBy(student -> "南京大学".equals(student.getSchool())));
举报

相关推荐

0 条评论