宁武皇仁光九年锦文轩刻本《异闻录》载: 扶桑画师浅溪,居泰安,喜绘鲤。院前一方荷塘,锦鲤游曳,溪常与嬉戏。 其时正武德之乱,潘镇割据,战事频仍,魑魅魍魉,肆逆于道。兵戈逼泰安,街邻皆逃亡,独溪不舍锦鲤,未去。 是夜,院室倏火。有人入火护溪,言其本鲤中妖,欲取溪命,却生情愫,遂不忍为之。翌日天明,火势渐歇,人已不见。 溪始觉如梦,奔塘边,但见池水干涸,莲叶皆枯,塘中鲤亦不知所踪。 自始至终,未辨眉目,只记襟上层迭莲华,其色魅惑,似血着泪。 后有青岩居士闻之,叹曰:魑祟动情,必作灰飞。犹蛾之投火耳,非愚,乃命数也。 ————《锦鲤抄》

【java8 Stream日常学习使用】

Stream学习 ——2022.05.31

简介

​ Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的Lambda ,给我们操作集合(Collection)提供了极大的便利。Stream流是JDK8的特性,允许以声明性方式处理数据集合,可以把Stream流看作是遍历数据集合的一个高级迭代器。Stream 是 Java8 中处理集合的关键抽象概念,,可以执行非常复杂的查找/筛选/过滤、排序、聚合和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

​ 但是要注意,虽然Stream api某种意义上可以代替sql,但是并不建议完全代替,因为当数据量过大或者访问压力 大的时候还是需要数据库这种专业的数据处理引擎去处理,stream api 只是让代码更简洁好看,所以我的建议是,对于操作数据量不大的集合需求可以用stream一试。

至于 lambda 表达式,也是代码简洁化的一种,可以和stream 一起学习:

常见的使用

​ 最常用创建的方式:通过 java.util.Collection.stream() 方法用集合创建流

测试用例:

Collectors.groupingBy 分组
  • 根据单个字段分组:
 Map<String, List<Capcom>> collectMap = capList.stream().collect(Collectors.groupingBy(Capcom::getVersion));

PS:// Capcom::getVersion 即 capcom -> capcom.getVersion(),::也叫方法引用

  • 根据多个字段分组,注意,这里写了个dto来存放分组字段

​ 当然,不借助实体类直接拼接字段也可以:

排序stream().sorted()
  • 根据字段排序 stream().sorted(),下面列出三种情况:
 /**
         * 按照score进行排序
         * 1. 自定义升序
         * 2. 自定义降序
         * 3.多字段升序,score 升序,若相同则根据 c_num 继续判断
         */
        List<Capcom> ascOrder = new ArrayList();
        List<Capcom> descOrder = new ArrayList();
        List<Capcom> multOrder = new ArrayList();

        ascOrder = capList.stream().sorted(Comparator.comparing(Capcom::getScore)).collect(Collectors.toList());
        descOrder = capList.stream().sorted(Comparator.comparing(Capcom::getScore).reversed()).collect(Collectors.toList());
        multOrder = capList.stream().sorted(Comparator.comparing(Capcom::getScore).thenComparing(Capcom::getcNum)).collect(Collectors.toList());

MIN 和 MAX
// min 和 max,以max为例
List<Integer> list = Arrays.asList(3, 45, 675, 2, 5);
Optional<Integer> max = list.stream().max(Integer::compareTo);
// 自定义排序
Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1.compareTo(o2);
    }
});
System.out.println(max2);
//输出: Optional[675]
filter 筛选

条件筛选过滤;

reduce 规约

​ 规约,可将流缩减为一个值

       // reduce 规约,可将流缩减为一个值
        Optional<Long> reSum = capList.stream().map(Capcom::getCapId).reduce(Long::sum);
        Optional<Long> reMax = capList.stream().map(Capcom::getCapId).reduce(Long::max);

        Optional<BigDecimal> decimalSum = capList.stream().map(Capcom::getScore).reduce(BigDecimal::add);
        Optional<BigDecimal> decimalMax = capList.stream().map(Capcom::getScore).reduce(BigDecimal::max);
        System.out.println(" long sum: "+reSum + " long max :" + reMax + " decimal sum :" + decimalSum +" decimal max :" + decimalMax);
        // 假设有tmpList,需要求list中某金额字段endNetBalance的 sum合计,如下:
        Bigdecimal sum = tmpList.stream().map(TraArHeader::getEndNetBalance).reduce(BigDecimal::add).get();

        // 输出:long sum: Optional[7028] long max :Optional[1007] decimal sum :Optional[600] decimal max :Optional[90]
toSet 和 toMap

数据汇总为Set或者Map;

        // toSet, toMap
        Set<String> numberSet = capList.stream().map(Capcom::getcNum).collect(Collectors.toSet());
        Map<String, Capcom> mapCollect = capList.stream().filter(x -> x.getCapId() < 1003).collect(Collectors.toMap(Capcom::getcNum, y -> y));
        System.out.println("编号合集 num Set:" +numberSet + "mapCollect :" + mapCollect);
        /**
         * 输出:
         * 编号合集 num Set:[0007, 0004, 0005, 0002, 0003, 0000, 0001]
         *        mapCollect :{0002=Capcom{capId=1002, cName='卡洛斯·奥利维拉', cNum='0002', version='1', score=83}, 
         *                    0001=Capcom{capId=1001, cName='吉尔.瓦伦蒂安', cNum='0001', version='1', score=87}}
         */
lambda结合stream

​ 有的时候编译器会提示建议转换为lambda表达式,本质上lambda表达式的语法由参数列表、箭头符号->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块。下面第二个例子就是一种常见的遍历更新。

        // 例子1:lambda 结合 stream 实现map
        List<Double> values = Arrays.asList(10.0, 20.0,30.0);
        // 增加了0.05倍
        values = values.stream().map(x -> x + x*0.05).collect(Collectors.toList());
        /**
         * values toString显示: [10.5, 21.0, 31.5]
         */

        // 例子2:包含函数体:遍历判断并更新赋值
        capList.stream().filter(line -> StringUtils.isNotEmpty(line.getcNum())).map(line -> {
            line.setVersion("999");
            return line;
        }).collect(Collectors.toList());
        /**
         *  当前capList更新为:
         *  [Capcom{capId=1001, cName='吉尔.瓦伦蒂安', cNum='0001', version='999', score=87}, 
         *  Capcom{capId=1002, cName='卡洛斯·奥利维拉', cNum='0002', version='999', score=83}, 
         *  Capcom{capId=1003, cName='里昂·斯科特·肯尼迪', cNum='0003', version='999', score=90}, 
         *  Capcom{capId=1004, cName='克莱尔·雷德菲尔德', cNum='0004', version='999', score=80}, 
         *  Capcom{capId=1005, cName='克里斯·雷德菲尔德', cNum='0005', version='999', score=90}, 
         *  Capcom{capId=1006, cName='Ada.wang', cNum='0000', version='999', score=90}, 
         *  Capcom{capId=1007, cName='伊森', cNum='0007', version='999', score=80}]
         */
posted @ 2022-05-31 17:24  哒布溜  阅读(81)  评论(0编辑  收藏  举报