• java8特性Stream流和lambda表达式在实际开发中应用


    1.前言

    在实际工作开发中,会经常用到stream流Api来进行数据处理,转换和筛选等。尤其是lambda表达式和流API结合可以写出更加干净的代码。

    2.lambda表达式介绍

    Lambda表达式 --> 函数式编程(函数编程思想)
    标准格式:
    (参数列表) -> {代码}

    举个列子,可以利用lambda表达式来实现Runnable,用() -> {}代码块替代了整个匿名类,从而创建线程。

    // Java 8之前:
    new Thread(new Runnable() {
        @Override
        public void run() {
        System.out.println("Before Java8, too much code for too little to do");
        }
    }).start();
    
    //lambda方式:
    new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这个例子向我们展示了Java 8 lambda表达式的语法。你可以使用lambda写出如下代码:

    (params) -> expression
    (params) -> statement
    (params) -> { statements } 
    
    • 1
    • 2
    • 3

    2.Stream流api的介绍

    作用:简化集合、数组操作的API。结合了Lambda表达式。

    Stream流的三类方法

    • 获取Stream流(下面主要介绍)
      创建一条流水线,并把数据放到流水线上准备进行操作
      在这里插入图片描述

    • 中间方法
      流水线上的操作。一次操作完毕之后,还可以继续进行其他操作。
      在这里插入图片描述

    • 终结方法
      一个Streami流只能有一个终结方法,是流水线上的最后一个操

    在这里插入图片描述

    3.stream流测试案例

      public static void main(String args[]){
    
        // 集合获取stream流
        List<String> list = Lists.newArrayList();
        Stream<String> s = list.stream();
    
        // map集合获取流
        Map<String,Integer> map = new HashMap<>();
        // 获取键流
        Stream<String> keyStream = map.keySet().stream();
        // 值流
        Stream<Integer> valueStream = map.values().stream();
        // 获取键值对数据流
        Stream<Map.Entry<String,Integer>> keyAndValueStream = map.entrySet().stream();
    
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 定义一个集合
    @Data
    public static class OrderInfo implements Serializable {
    
     //详情id
     private Integer id;
     //订单号
     private String orderNo;
     //商品id
     private Integer goodsId;
     //商品名称
     private String name;
     //商品单价
     private BigDecimal price;
     //商品数量
     private BigDecimal num;
     public OrderInfo(Integer id, String orderNo, Integer goodsId, String name, BigDecimal price, BigDecimal num) {
       this.id = id;
       this.orderNo = orderNo;
       this.goodsId = goodsId;
       this.name = name;
       this.price = price;
       this.num = num;
     }
    }
    public static void main(String[] args){
    
    
     List<OrderInfo> orderInfoList = Lists.newArrayList();
     OrderInfo info = new OrderInfo(1,"N001", 1, "香蕉", new BigDecimal("2.3"), new BigDecimal(2));
     orderInfoList.add(info);
     info = new OrderInfo(2,"N001", 2, "苹果", new BigDecimal("4.3"), new BigDecimal("3.5"));
     orderInfoList.add(info);
     info = new OrderInfo(3,"N002", 3, "橘子", new BigDecimal("3.3"), new BigDecimal(4));
     orderInfoList.add(info);
     info = new OrderInfo(4,"N003", 1, "香蕉", new BigDecimal("2.3"), new BigDecimal("3.4"));
     orderInfoList.add(info);
     info = new OrderInfo(5,"N003", 3, "橘子", new BigDecimal("3.3"), new BigDecimal("3.5"));
     orderInfoList.add(info);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 数据流具体操作
      // list对象类型转化为map(key是id,value为OrderInfo)
      Map<Integer,OrderInfo> listToMap1 = orderInfoList.stream().collect(
          Collectors.toMap(OrderInfo::getId,orderInfo -> orderInfo)
      );
      
      // list对象转化为map存在重复key的情况(保存重复key的第一条记录)
      Map<Integer, OrderInfo> listToMap2 = orderInfoList.stream().collect(
          Collectors.toMap(OrderInfo::getGoodsId,Function.identity(),(k1,k2)->k1)
      );
    
      // list对象转化为map(key是id,value为商品名称)
      Map<Integer,String> listToMap3 = orderInfoList.stream().collect(
          Collectors.toMap(OrderInfo::getId,OrderInfo::getName)
      );
      
        // list对象转化为map(key是orderNo,value为list,又一个按照orderNo聚合操作)
      Map<String,List<OrderInfo>> listToMap4 = orderInfoList.stream().collect(
          Collectors.groupingBy(OrderInfo::getOrderNo)
      );
    
      // list对象转化为map(key是orderNo,value为商品id的List列表)
      Map<String,List<Integer>> listToMap5 = orderInfoList.stream().collect(
          Collectors.groupingBy(OrderInfo::getOrderNo,Collectors.mapping(OrderInfo::getGoodsId,Collectors.toList()))
      );
      
      // list对象转化为map(key是orderNo,value为订单对应的总价格)
      Map<String,Double> listToMap6 = orderInfoList.stream().collect(
          Collectors.groupingBy(OrderInfo::getOrderNo,Collectors.summingDouble(
              orderInfo -> orderInfo.getNum().multiply(orderInfo.getPrice()).doubleValue()
          ))
      );
    
      // 遍历转化的map
      System.out.println(JSON.toJSONString(listToMap6));
      listToMap6.forEach((key,value)->{
        System.out.println(key+":"+value);
      });
    
    // list对象转化为list(获取商品的id,组成列表,不去重)
      List<Integer> listToIdList = orderInfoList.stream().map(OrderInfo::getGoodsId)
          .collect(Collectors.toList());
    
    
      // list对象转化为list(获取商品的id,组成列表,去重复)
      List<Integer> listToIdList1 = orderInfoList.stream().map(OrderInfo::getGoodsId)
          .distinct().collect(Collectors.toList());
    
    
      // 对list进行筛选,(单价大于4元的订单详情列表)
      List<OrderInfo> listToFilterList = orderInfoList.stream().filter(
          orderInfo -> orderInfo.getPrice().doubleValue()>4).collect(Collectors.toList());
    
    
      // 对list筛选,获取单价大于3元且数量大于等于4的订单列表
      List<OrderInfo> listToFilterList1 = orderInfoList.stream().filter(
          orderInfo -> orderInfo.getPrice().doubleValue()>3 && orderInfo.getNum().doubleValue()>=4
      ).collect(Collectors.toList());
    
    
      // 按照价格,对list进行排序(价格从大到小)
      List<OrderInfo> listToSortList = orderInfoList.stream().sorted(
          Comparator.comparing(OrderInfo::getPrice).reversed()
      ).collect(Collectors.toList());
    
    
      //价格从小到大排序,数量从小到大排序
      List<OrderInfo> listToSortList1 = orderInfoList.stream().sorted(
          Comparator.comparing(OrderInfo::getPrice).thenComparing(OrderInfo::getNum)
      ).collect(Collectors.toList());
    
    
      // 价格从小到大,数量从大到小
      Comparator<OrderInfo> c1 = Comparator.comparing(OrderInfo::getPrice);
      Comparator<OrderInfo> c2 = Comparator.comparing(OrderInfo::getNum).reversed();
      List<OrderInfo> listToSortList2 = orderInfoList.stream().sorted(
          c1.thenComparing(c2)
      ).collect(Collectors.toList());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    4.Java 8中使用lambda表达式的Map和Reduce示例

    map将集合类(例如列表)元素进行转换的。还有一个 reduce() 函数可以将所有值合并成一个。Map和Reduce操作是函数式编程的核心操作,因为其功能,reduce 又被称为折叠操作。另外,reduce 并不是一个新的操作,你有可能已经在使用它。SQL中类似 sum()、avg() 或者 count() 的聚集函数,实际上就是 reduce 操作,因为它们接收多个值并返回一个值。流API定义的 reduceh() 函数可以接受lambda表达式,并对所有值进行合并。IntStream这样的类有类似 average()、count()、sum() 的内建方法来做 reduce 操作,也有mapToLong()、mapToDouble() 方法来做转换。这并不会限制你,你可以用内建方法,也可以自己定义。在这个Java 8的Map Reduce示例里,我们首先对所有价格应用 12% 的VAT,然后用 reduce() 方法计算总和。

    // 为每个订单加上12%的税
    // 老方法:
    List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
    double total = 0;
    for (Integer cost : costBeforeTax) {
        double price = cost + .12*cost;
        total = total + price;
    }
    System.out.println("Total : " + total);
    
    // 新方法:
    List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
    double bill = costBeforeTax.stream().map((cost) -> cost + .12*cost).reduce((sum, cost) -> sum + cost).get();
    System.out.println("Total : " + bill); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    Vue项目打包部署到Gitee Pages配置教程(无空白bug)
    01.cesium简介
    【Java Web】HTML 标签 总结
    一览「数字身份」市场结构:我们将在元宇宙中成为谁?
    华为云云耀云服务器L实例评测|利用云服务器部署个人博客站
    基于深度学习的红外船舶检测识别分类完整实现数据集8000+张
    2022速卖通官方披露;婚纱服饰品类策略及机会品类推荐
    k8s如何优雅地关闭Pod
    相关性网络图
    C++ Reference: Standard C++ Library reference: C Library: cwchar: wcsxfrm
  • 原文地址:https://blog.csdn.net/maligebilaowang/article/details/127648184