对Stream API结合Lambda 表达式学习及总结(1)

Stream API介绍

Stream API 是 Java 8 中引入的一项功能,它提供了一种新的抽象层,允许你以声明性方式处理数据集合(如列表、集合等)。Stream API 可以极大地简化集合操作的编码工作,支持顺序和并行处理。

核心特点

声明性:通过 Stream API,你可以写出更简洁且易于理解的代码来描述你想要执行的数据操作,而不是如何执行。
可组合:Stream 操作可以链接起来,形成一个流水线,这样可以在一系列操作中传递和变换数据。
并行能力:Streams 可以非常简单地进行并行操作,只需改变一个方法调用,就可以利用多核处理器的能力,提高程序性能。
只消费一次:Stream 只能被消费一次,一旦你遍历过或者终结了一个 Stream,就不能再次使用了。

常见操作

中间操作:这些操作处理流并返回一个新的流,如 filter, map, sorted 等。
终端操作:这些操作关闭流并产生结果,如 forEach, collect, reduce 等。

Lambda 表达式

Lambda 表达式,也是在 Java 8 中引入的,它提供了一种清晰且简洁的方式来表示一次性传递的方法(即匿名方法)。Lambda 表达式用于提供函数式编程的能力,可以用更少的代码实现更多的功能。

核心特点

简洁性:Lambda 表达式消除了匿名类的冗余代码,使代码更加简洁。
函数式风格:通过引入函数式编程特征,Lambda 表达式支持将函数作为方法参数,或将代码作为数据对待。
灵活性:Lambda 表达式可以用作任何函数式接口(只有一个抽象方法的接口)的实例。

结合使用

Stream API 和 Lambda 表达式经常结合使用,因为它们互相补充:Stream API 提供了处理数据的高级抽象,而 Lambda 表达式提供了简洁的语法来表达行为或操作。这种结合提供了强大的工具集,用于处理集合数据,支持更复杂的数据处理任务,同时代码更加简洁易读。

以下是例子及代码解析

eg1:功能介绍:

代码的主要功能是从数据库获取所有产品信息(ProductInfo 对象),然后将这些信息转换为另一种类型的对象(ProductInfoVo),并最终收集成一个列表。这种模式在处理数据转换和数据层到服务层或控制层的数据传递中非常常见。

list = productInfoMapper.all().stream().map(i -> {
                ProductInfoVo vo = new ProductInfoVo();
                BeanUtils.copyProperties(i, vo);
                return vo;
            }).collect(Collectors.toList());

详细解析:

productInfoMapper.all()

这个方法调用 productInfoMapper 的 all 方法,通常这样的 Mapper 类是 MyBatis 或类似持久层框架的一部分,用于从数据库获取所有 ProductInfo 实例的集合。

.stream()

调用 stream() 方法将获取的集合转换为一个流(Stream)。流(Stream)是 Java 8 引入的一个抽象概念,它允许你以一种声明式的方式处理数据集合(例如数组或列表)。

.map(i -> {
    ProductInfoVo vo = new ProductInfoVo();
    BeanUtils.copyProperties(i, vo);
    return vo;
})

使用 map 函数转换流中的每个元素。对于流中的每个 ProductInfo 实例 i:
创建一个新的 ProductInfoVo 对象 vo。
使用 BeanUtils.copyProperties(i, vo); 方法将 i 的属性复制到 vo。这里 BeanUtils 是 Spring Framework 提供的一个工具类,用于对象之间的属性复制。
最后,映射函数返回新的 vo 对象。这样,原始的 ProductInfo 实例被转换为 ProductInfoVo 实例。

.collect(Collectors.toList());

最终,使用 collect 方法将转换后的流元素收集到一个新的列表中。Collectors.toList() 是一个收集器,用于把流中的元素累积到一个新的 List 中。

eg2:功能介绍:

这段代码是在 Java 中使用 Stream API 对一个 Product 类型的列表进行多阶段的复杂排序和筛选处理。

productList = (List<Product>) productList.stream().sorted(
                        Comparator.comparing(Product::getTotalLoanDay, Comparator.reverseOrder())
                                .thenComparing(Product::getPeriodCapacity,
                                        (a, b) -> b == 15 ? 1 : (a == 15 ? -1 : 0)))
                .limit(2).sorted(
                        Comparator.comparing(Product::getProductCode, ((a, b) -> {
                            if (productCodeList.contains(a)&&productCodeList.contains(b)) {
                                return 0;
                            }else if(productCodeList.contains(b)){
                                return -1;
                            }else if(productCodeList.contains(a)){
                                return 1;
                            }
                            return 0;
                        }))).sorted(
                Comparator.comparing(o -> o, ((a, b) ->{
                    if(a.getProductCode().startsWith("I")){
                        return 1;
                    }else {
                        return -1;
                    }
                }))
        ).collect(Collectors.toList());

详细解析:
首先,这是一个对 productList 进行多级排序和筛选的过程,最终将处理后的流重新收集为一个列表。这个过程分为几个主要步骤:

sorted(Comparator.comparing(Product::getTotalLoanDay, Comparator.reverseOrder())
        .thenComparing(Product::getPeriodCapacity, (a, b) -> b == 15 ? 1 : (a == 15 ? -1 : 0)))

这里首先根据 Product 的 getTotalLoanDay 方法返回的值进行降序排序。
thenComparing 进一步定义了排序规则,如果 getTotalLoanDay 相同,则根据 getPeriodCapacity 排序。如果 getPeriodCapacity 为 15,该产品将被视为优先(自定义排序逻辑使得值为15的产品排序靠后)。

.limit(2)

这个操作限制了流中的元素数量最多为2,即只保留前两个元素。

sorted(Comparator.comparing(Product::getProductCode, (a, b) -> {
    if (productCodeList.contains(a) && productCodeList.contains(b)) {
        return 0;
    } else if (productCodeList.contains(b)) {
        return -1;
    } else if (productCodeList.contains(a)) {
        return 1;
    }
    return 0;
}))

第二次排序:根据 Product 的 getProductCode 进行排序。排序逻辑依赖于一个外部的 productCodeList 集合,判断产品代码是否存在于该集合中。
如果两个产品代码都在列表中或都不在列表中,它们相等。
如果仅其中一个在列表中,存在于列表中的产品代码视为较小(即优先排序)。

sorted(Comparator.comparing(o -> o, (a, b) -> {
    if (a.getProductCode().startsWith("I")) {
        return 1;
    } else {
        return -1;
    }
}))

第三次排序:最后一次排序依据是否产品代码以 “I” 开头。以 “I” 开头的视为较大。
这意味着,不以 “I” 开头的产品在排序时会被提前。

.collect(Collectors.toList())

经过排序和筛选后的流被收集回一个新的列表。

eg3:功能介绍:

这段代码使用了Java的Stream API和BigDecimal类,以执行一系列操作,其目的是从一个CreditResultProductInfo对象的列表中找出可用产品的最小金额

BigDecimal minAmount = creditResultProductInfoList.stream().filter(CreditResultProductInfo::isAvailable).map(productInfo -> new BigDecimal(productInfo.getAmount())).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);	

代码详细分析

creditResultProductInfoList.stream().filter(CreditResultProductInfo::isAvailable)

creditResultProductInfoList:假设这是一个包含CreditResultProductInfo类型对象的列表。
stream():将列表转换成一个流,以便进行一系列流操作。
filter(CreditResultProductInfo::isAvailable):使用filter方法筛选出列表中可用的产品。CreditResultProductInfo::isAvailable是一个方法引用,它调用CreditResultProductInfo类的isAvailable方法,该方法应该返回一个布尔值,指示产品是否可用。

.map(productInfo -> new BigDecimal(productInfo.getAmount()))

map方法用于将流中的每个CreditResultProductInfo对象转换成一个BigDecimal实例。
productInfo.getAmount():假设这个方法返回产品的金额,可能是字符串或数值类型,这里用于初始化BigDecimal对象。

.min(BigDecimal::compareTo)

min方法是一个终端操作,它接受一个比较器并返回流中的最小值。这里使用BigDecimal::compareTo作为比较器,它是BigDecimal内建的比较方法,用于比较两个BigDecimal对象的大小。

.orElse(BigDecimal.ZERO)

orElse(BigDecimal.ZERO):如果min方法找不到任何元素(即流为空,可能是因为没有任何产品标记为可用),则返回BigDecimal.ZERO。这是为了确保minAmount变量在任何情况下都有一个合法的值,避免NullPointerException。

未完待续。。。。

  • 14
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值