樂字節-Java8新特性之Stream流(下)

接上一篇:《Java8新特性之stream》,下面繼續接着講Streamjava

五、流的中間操做

常見的流的中間操做,歸爲如下三大類:篩選和切片流操做、元素映射操做、元素排序操做:
圖片描述segmentfault

5.一、篩選和切片

例如以訂單數據爲例,在作報表展現時,會根據訂單狀態、用戶信息、支付結果等狀態來分別展現(即過濾和統計展現)ide

定義訂單Order類測試

public class Order {
    // 訂單id
    private Integer id;
    // 訂單用戶id
    private Integer userId;
    // 訂單編號
    private  String orderNo;
    // 訂單日期
    private Date orderDate;
    // 收貨地址
    private String address;
    // 建立時間
    private Date createDate;
    // 更新時間
    private Date updateDate;
    // 訂單狀態  0-未支付  1-已支付  2-代發貨  3-已發貨  4-已接收  5-已完成
    private Integer status;
    // 是否有效  1-有效訂單  0-無效訂單
    private Integer isValid;
    
    //訂單總金額
    private  Double total;
    /**
       此處省略getter/setter方法
    */
}

測試this

public static void main(String[] args) {
        Order order01 = new Order(1,10,"20190301",
                new Date(),"上海市-浦東區",new Date(),new Date(),4,1,100.0);
        Order order02 = new Order(2,30,"20190302",
                new Date(),"北京市四惠區",new Date(),new Date(),1,1,2000.0);
        Order order03 = new Order(3,20,"20190303",
                new Date(),"北京市-朝陽區",new Date(),new Date(),4,1,500.0);
        Order order04 = new Order(4,40,"20190304",
                new Date(),"北京市-大興區",new Date(),new Date(),4,0,256.0);
        Order order05 = new Order(5,40,"20190304",
                new Date(),"上海市-松江區",new Date(),new Date(),4,0,1000.0);
        List<Order> ordersList= Arrays.asList(order01,order02,order03,order04);
        // 過濾訂單集合 有效訂單 並打印到控制檯
        ordersList.stream().filter((order)->order.getIsValid()==1).forEach(System.out::println);
        // 過濾訂單集合有效訂單 取前兩條有效訂單 並打印到控制檯
        ordersList.stream().filter((order)->order.getIsValid()==1).limit(2).forEach(System.out::println);
    }
         // 過濾訂單集合有效訂單 取最後一條記錄
        ordersList.stream().filter((order)->order.getIsValid()==1)
                .skip(ordersList.size()-2).forEach(System.out::println);

// 去除訂單編號重複的無效訂單記錄 此時由於比較的爲Object Order對象須要重寫HashCode 與Equals 方法
/**
     * 重寫 equals 方法
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        boolean flag = false;
        if (obj == null) {
            return flag;
        }
        Order order = (Order) obj;
        if (this == order) {
            return true;
        } else {
            return (this.orderNo.equals(order.orderNo));
        }
    }

    /**
     * 重寫hashcode方法
     * @return
     */
    @Override
    public int hashCode() {
        int hashno = 7;
        hashno = 13 * hashno + (orderNo == null ? 0 : orderNo.hashCode());
        return hashno;
    }
 // 過濾訂單集合無效訂單 去除訂單號重複記錄
  ordersList.stream().filter((order)->order.getIsValid()==0).distinct().forEach(System.out::println);

5.二、映射

//過濾訂單集合有效訂單  獲取全部訂單訂單編號
ordersList.stream().filter((order)->order.getIsValid()==1).map((order)->order.getOrderNo()).forEach(System.out::println);

// 過濾有效訂單  並分離每一個訂單下收貨地址市區信息
ordersList.stream().map(o->o.getAddress().split("-")).flatMap(Arrays::stream).forEach(System.out::println);

5.三、排序

//過濾有效訂單 並根據用戶id 進行排序
 ordersList.stream().filter((order)->order.getIsValid()==1)
 .sorted((o1,o2)->o1.getUserId()-o2.getUserId()).forEach(System.out::println);
//或者等價寫法
ordersList.stream().filter((order)->order.getIsValid()==1)
                .sorted(Comparator.comparingInt(Order::getUserId)).forEach(System.out::println);

// 定製排序規則
/*過濾有效訂單
 * 定製排序:若是訂單狀態相同 根據訂單建立時間排序 反之根據訂單狀態排序
*/
ordersList.stream().filter((order)->order.getIsValid()==1).sorted((o1,o2)->{
   if(o1.getStatus().equals(o2.getStatus())){
        return o1.getCreateDate().compareTo(o2.getCreateDate());
    }else{
        return o1.getStatus().compareTo(o2.getStatus());
    }}).forEach(System.out::println);

六、流的終止操做

終止操做會從流的流水線生成結果。其結果是任何不是流的值,好比常見的List、 Integer,甚 至void等結果。spa

對於流的終止操做,分爲如下三類:code

圖片描述

6.一、查找與匹配

// 篩選全部有效訂單  匹配用戶id =20 的全部訂單
System.out.println("allMatch匹配結果:"+ordersList.stream().
                   filter((order) -> order.getIsValid() == 1).allMatch((o) -> o.getUserId() == 20));
System.out.println("anyMatch匹配結果:"+ordersList.stream().
                   filter((order) -> order.getIsValid() == 1).anyMatch((o) -> o.getUserId() == 20));
System.out.println("noneMatch匹配結果:"+ordersList.stream().
                   filter((order) -> order.getIsValid() == 1).noneMatch((o) -> o.getUserId() == 20));

//  篩選全部有效訂單 返回訂單總數
System.out.println("count結果:"+ordersList.stream().
                   filter((order) -> order.getIsValid() == 1).count());
// 篩選全部有效訂單 返回金額最大訂單值
Optional<Double> max=ordersList.stream().filter((order) -> order.getIsValid() == 1)
    .map(Order::getTotal).max(Double::compare);
System.out.println("訂單金額最大值:"+max.get());
// 篩選全部有效訂單 返回金額最小訂單值
Optional<Double> min=ordersList.stream().filter((order) -> order.getIsValid() == 1)
    .map(Order::getTotal).min(Double::compare);
System.out.println("訂單金額最小值:"+min.get());

6.二、歸約

將流中元素反覆結合起來,獲得一個值的操做。

// 歸約操做  計算有效訂單總金額
System.out.println("有效訂單總金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1).map(Order::getTotal).reduce(Double::sum).get());

6.三、Collector收集數據

6.3.一、收集對象

將流轉換爲其餘形式,coollect 方法做爲終端操做, 接收一個Collector接口的實現,用於給Stream中元素作彙總的方法。最經常使用的方法,把流中全部元素收集到一個 List, Set 或 Collection 中排序

  • toList
  • toSet
  • toCollection
  • toMap接口

    // 收集操做
    // 篩選全部有效訂單 並收集訂單列表
    List<Order> orders= ordersList.stream().filter((order) -> order.getIsValid() == 1).collect(Collectors.toList());
    orders.forEach(System.out::println);
    // 篩選全部有效訂單 並收集訂單號 與 訂單金額
    Map<String,Double> map=ordersList.stream().filter((order) -> order.getIsValid() == 1).

    collect(Collectors.toMap(Order::getOrderNo, Order::getTotal));

    // java8 下對map 進行遍歷操做 若是 Map 的 Key 重複了,會報錯
    map.forEach((k,v)->{

    System.out.println("k:"+k+":v:"+v);

    });

6.3.二、彙總

  • countintg():用於計算總和
  • count():用於計算總和(推薦使用,寫法更簡潔)
  • summingInt() ,summingLong(),summingDouble():用於計算總和
  • averagingInt(),averagingLong(),averagingDouble()用於平均
  • summarizingInt,summarizingLong,summarizingDouble 一樣能夠實現計算總和,平均等操做,好比summarizingInt 結果會返回IntSummaryStatistics 類型 ,而後經過get方法獲取對應彙總值便可

    // 彙總操做
    //篩選全部有效訂單 返回訂單總數
    System.out.println("count結果:"+ordersList.stream().

    filter((order) -> order.getIsValid() == 1).collect(Collectors.counting()));

    System.out.println("count結果:"+ordersList.stream().

    filter((order) -> order.getIsValid() == 1).count());

    // 返回訂單總金額
    System.out.println("訂單總金額:"+ordersList.stream().

    filter((order) -> order.getIsValid() == 1).collect(Collectors.summarizingDouble(Order::getTotal)));

    System.out.println("訂單總金額:"+ordersList.stream().

    filter((order) -> order.getIsValid() == 1).mapToDouble(Order::getTotal).sum());

    System.out.println("訂單總金額:"+ordersList.stream().

    filter((order) -> order.getIsValid() == 1).map(Order::getTotal).reduce(Double::sum).get());

    // 返回 用戶id=20 有效訂單平均每筆消息金額
    System.out.println("用戶id=20 有效訂單平均每筆消費金額:"+ordersList.stream().

    filter((order) -> order.getIsValid() == 1).
                   filter((order -> order.getUserId()==20))
                   .collect(Collectors.averagingDouble(Order::getTotal)));

    System.out.println("用戶id=20 有效訂單平均每筆消費金額:"+

    ordersList.stream().
                   filter((order) -> order.getIsValid() == 1).
                   filter((order -> order.getUserId()==20))
                   .mapToDouble(Order::getTotal).average().getAsDouble());

    System.out.println("用戶id=20 有效訂單平均每筆消費金額:"+

    ordersList.stream().
                   filter((order) -> order.getIsValid() == 1).
                   filter((order -> order.getUserId()==20))
                   .collect(Collectors.summarizingDouble(Order::getTotal)).getAverage());

    // 篩選全部有效訂單 並計算訂單總金額
    System.out.println("訂單總金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)

    .collect(Collectors.summingDouble(Order::getTotal)));

    // 篩選全部有效訂單 並計算最小訂單金額
    System.out.println("最小訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)

    .map(Order::getTotal).collect(Collectors.minBy(Double::compare)));

    // 篩選全部有效訂單 並計算最大訂單金額
    System.out.println("最大訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)

    .map(Order::getTotal).collect(Collectors.maxBy(Double::compare)));

6.3.三、最值

maxBy,minBy 兩個方法,須要一個 Comparator 接口做爲參數,實現最大 最小值獲取操做

// 取最會
// 篩選全部有效訂單 並計算最小訂單金額
System.out.println("最小訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)
                   .map(Order::getTotal).collect(Collectors.minBy(Double::compare)));
// 篩選全部有效訂單 並計算最大訂單金額
System.out.println("最大訂單金額:"+ordersList.stream().filter((order) -> order.getIsValid() == 1)
                   .map(Order::getTotal).collect(Collectors.maxBy(Double::compare)));

6.3.四、分組

groupingBy 用於將數據分組,最終返回一個 Map 類型

groupingBy 能夠接受一個第二參數實現多級分組

// 分組-根據有效訂單支付狀態進行分組操做
Map<Integer,List<Order>> g01=ordersList.stream().filter((order) -> order.getIsValid() == 1)
    .collect(Collectors.groupingBy(Order::getStatus));
g01.forEach((status,order)->{
    System.out.println("----------------");
    System.out.println("訂單狀態:"+status);
    order.forEach(System.out::println);
});

// 分組-查詢有效訂單 根據用戶id 和 支付狀態進行分組
Map<Integer,Map<String,List<Order>>> g02= ordersList.stream().filter((order) -> order.getIsValid() == 1)
    .collect(Collectors.groupingBy(Order::getUserId,Collectors.groupingBy((o)->{
        if(o.getStatus()==0){
            return "未支付";
        }else if (o.getStatus()==1){
            return "已支付";
        }else if (o.getStatus()==2){
            return "待發貨";
        }else if (o.getStatus()==3){
            return "已發貨";
        }else if (o.getStatus()==4){
            return "已接收";
        } else{
            return "已完成";
        }
    })));
g02.forEach((userId,m)->{
    System.out.println("用戶id:"+userId+"-->有效訂單以下:");
    m.forEach((status,os)->{
        System.out.println("狀態:"+status+"---訂單列表以下:");
        os.forEach(System.out::println);
    });
    System.out.println("-----------------------");
});

6.3.五、partitioningBy 分區

分區與分組的區別在於,分區是按照 true 和 false 來分的,所以partitioningBy 接受的參數的 lambda 也是 T -> boolean 

// 分區操做  篩選訂單金額>1000 的有效訂單
Map<Boolean,List<Order>> g03= ordersList.stream().filter((order) -> order.getIsValid() == 1)
    .collect(Collectors.partitioningBy((o)->o.getTotal()>1000));
g03.forEach((b,os)->{
    System.out.println("分區結果:"+b+"--列表結果:");
    os.forEach(System.out::println);
});

// 拼接操做 篩選有效訂單 並進行拼接
String orderStr=ordersList.stream().filter((order) -> order.getIsValid() == 1).map(Order::getOrderNo)
    .collect(Collectors.joining(","));
System.out.println(orderStr);

樂字節-Java新特性之stream流就介紹到這裏了,接下來小樂還會接着給你們講解Java8新特性之Optional,歡迎關注,轉載請說明出處和做者。

相關文章
相關標籤/搜索