Java 8流操作

Java 8中一个重大的改变是对核心类库的改进,新增的特性旨在帮助我们写出更加优秀的代码。对核心类库的改进主要包括集合类的 API 和新引入的流 (Stream)。流使程序员得以站在更高的抽象层次上对集合进行操作。

从外部迭代到内部迭代

外部迭代

我们在使用集合类时,最常用的就是利用for循环或者迭代器对集合进行操作,比如如下的代码:

private static List<Long> extractLongListValue(String productTags) {
    List<Long> list = new ArrayList<>();
    if (StringUtils.isBlank(productTags)) {
        return list;
    }
    String[] parts = productTags.split(",");
    for (String part : parts) {
        if(StringUtils.isBlank(part)){
            continue;
        }
        list.add(Long.valueOf(part));
    }
    return list;
}
复制代码

for循环其实是迭代器的语法糖,调用 iterator 方法,产生一个新的 Iterator 对象,进而控制整 个迭代过程,这就是外部迭代。迭代过程通过显式调用 Iterator 对象的 hasNext 和 next 方法完成迭代。

外部迭代的问题主要是:

  • 很难抽象一些通用操作。
  • 本质上是串行操作。

内部迭代

Java 8中的stream()方法为我们提供了使用内部迭代的机会。steam()不是返回一个控制迭代的 Iterator 对象,而是返回内部迭代中的相应接口:Stream。内部迭代将更多控制权交给了集合类,底层是通过访问者模式来实现。

改造后的代码:

private static List<Long> extractLongListValue(String productTags) {
        return Arrays.stream(productTags.split(Constant.COMMA)).filter(s -> StringUtils.isNotBlank(s)).map(Long :: valueOf).collect(
            Collectors.toList());
}
复制代码

直观的可以看到代码更加清晰简洁,业务逻辑清晰。如果有多个for循环嵌套,那么利用stream的优势将更加明显。

常用流操作

流上的操作主要分两种:

  • 惰性求值方法,只描述stream,不产生新集合,返回值为stream。类似建造者模式中的Builder。
  • 及早求值方法,最终会从stream产生值,具有终止操作,返回值为另一个值或空。

map

private static List<Long> extractLongListValue(String productTags) {
        return Arrays.stream(productTags.split(Constant.COMMA)).filter(s -> StringUtils.isNotBlank(s)).map(Long :: valueOf).collect(
            Collectors.toList());
}
复制代码

比如这段代码中,是利用LongvalueOf函数将类型为String流转换为类型为Long流。

filter

filter()功能是保留Stream中的一些元素,根据条件过滤掉其他元素。filter()需要传入一个Predicate函数接口的Lambda,Predicate接口传入一个对象,返回一个boolean。例如上述例子中的s -> StringUtils.isNotBlank(s)

collect

collect方法属于及早求值方法,传入一个收集器,将流生成一个复杂的结构。常用的收集器有:
(1)转换成其他集合
在上述例子中,我们就用了toList()收集器产生了一个新的List。在这里我们不需要指定类型,Stream类库会自动为我们挑选合适的类型。有时候我们需要产生一些特殊类型的集合,比如TreeSet,此时我们可以用toCollection()并传入TreeSet的构造函数:

stream.collect(Collectors.toCollection(TreeSet:new));
复制代码

(2)数据分组

groupingBy()的功能和SQL中的group by类似,根据值对流进行分组,最后返回一个map。

Map<Long, List<SkuDTO>> skuMap = skuList.stream().collect(groupingBy(SkuDTO::getSkuId));复制代码



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值