想快速处理元素?想将一个List快速转为另一个List或Map?Stream流轻松帮你搞定!

Java 8 API 添加了一个新的抽象称为流 Stream,可以让你以一种声明的方式处理数据,它提供了非常强大Java 集合运算和表达的高阶抽象。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理,可以把它看成一个工厂,流水线的形式(假如是玩具厂)。在这个流水线上,工人们对每个过来的玩具,进行处理,比如筛选、组装等。

Stream API可以极大提高Java程序员的生产力,省时省力还优雅。

下面我们来看看它的常见用法:

一、将List提取出某个字段生成List

List userIdList = userList.stream().map(User::getUserId).
        collect(Collectors.toList());
        

这行代码可以将userList中的userId转换为流 再用.collect(Collectors.toList())方法 提取为一个List集合,非常的方便高效。

另外,有的小伙伴可能需要过滤空字符等,可以用Stream流的 filter() 方法

List userAddressList = userList.stream().map(User::getAddress).
        filter(Objects::nonNull).
        collect(Collectors.toList());
        

这行代码 可以将userList的地址提取出来,且过滤掉地址为空的user对象。

二、将List根据某个字段生成Map

1、转换成对象某一字段与对象的Map

示例代码如下:

Map userIdWithUserMap = userList.stream().
        collect(Collectors.toMap(User::getUserId, User-> user));

这段代码可以以userId为key,user对象为value 组成一个map


2、转换成对象某一字段与对象另一字段的Map

示例代码如下:

Map userIdWithAgeMap = userList.stream().
        collect(Collectors.toMap(User::getUserId, User::getAge));

三、通过Stream流 将一个集合转换为另一个集合

List voList = userList.stream().map(item -> {
            UserVo vo = new UserVo();
            BeanUtils.copyProperties(item,vo);
            
            //vo可以进行别的操作
            //vo.set... 之类的

            return vo;
        }).collect(Collectors.toList());

上面这段代码通过Stream流的map()方法 可以将每个元素换成别的元素。可以将流看成一个流水线,userList的流一个一个过去 工人们将每个产品都将userList转换为 userVoList。 item是自定义名称 你也可以叫user 甚至a b c等(我不建议我不建议我不建议)

里面是使用了BeanUtils.copyProperties(item,vo); 来进行属性复制的操作。将item对象的属性赋值给vo对象。需要注意的是 item和vo的字段名需要对上 否则无法赋值成功。比如user有id name age三个属性,vo是userId, userName, age 三个属性 这时只有age能成功赋值。别的需要自己去set。

四、通过Stream流的sorted方法进行排序

我们偶尔会遇到想根据集合中的某个属性来进行排序的情况。

假设UserVo中 有个 distance 距离 属性。 我们想根据 distance 排序 怎么实现呢?

Stream流也可以做到:

List resultVoList = voList.stream()
            .sorted(Comparator.comparingDouble(UserVo::getDistance))
            .collect(Collectors.toList());

上面这行代码 使用了 Stream流的 sorted() 方法 将voList进行排序。 再使用.collect(Collectors.toList()); 将流转换为List集合。巧妙的实现了排序操作。

五、通过Stream流去重

有些小伙伴可能有去重的需求,我们知道set结构是去重的。

那么我们可以利用Stream的Collectors.toSet()来进行

Set userIdSet = userList.stream()
            .map(User::getUserId)
            .collect(Collectors.toSet());

这段代码就提取出了userList的id,并去重 赋值为一个Set集合。

六、计算总数

假设这是你的选手List,其中有 viewCount 是Long类型。那就可以如下:

List playerList = // 

// 计算总的 viewCount
long totalViewCount = playerList.stream()
            .mapToLong(Player::getViewCount)
            .sum();

那如果是String类型呢:

long totalViewCount = playerList.stream()
        .map(Player::getViewCount)
        .filter(viewCount -> viewCount != null && !viewCount.isEmpty()) // 过滤空值
        .mapToLong(Long::parseLong) // 转换为 Long 类型
        .sum();

//有空会继续补充。。

另外有些小伙伴会有疑问说For循环 增强For循环 Stream流 这三个的效率区别 Stream会不会比较慢等。

For循环 增强For循环 Stream流三者差别。

基本上 三者对于List操作 循环效率差别不大。

一定要对比一下的话,在循环次数较少的时候,基本上是Stream流的效率最低。为什么说是基本上,啊因为它大部分情况最低的。但是Stream可以通过parallel()方法开启并行流,随着CPU核心数的提升,和一些合理的场景运用,则会越来越快,这跟它基于的Fork/join框架有关。这个框架简单来说就是将可以并行的任务拆分成更小的任务来并行。后续我再出一篇细讲。

损失的一丁点性能,换来的是代码非常大程度的整洁和优雅。我个人还是非常推荐大家使用Stream流的。

好了。这部分先到这里,还有需要了解什么场景,或者我有些说的不太准确的地方,欢迎大家留言指正。谢谢!

你可能感兴趣的:(java)