接上一篇:《Java8新特性之stream》,下面继续接着讲Streamjava
常见的流的中间操做,归为如下三大类:筛选和切片流操做、元素映射操做、元素排序操做:segmentfault
例如以订单数据为例,在作报表展现时,会根据订单状态、用户信息、支付结果等状态来分别展现(即过滤和统计展现)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);
//过滤订单集合有效订单 获取全部订单订单编号 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);
//过滤有效订单 并根据用户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
// 筛选全部有效订单 匹配用户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());
将流中元素反复结合起来,获得一个值的操做。 // 归约操做 计算有效订单总金额 System.out.println("有效订单总金额:"+ordersList.stream().filter((order) -> order.getIsValid() == 1).map(Order::getTotal).reduce(Double::sum).get());
6.3.一、收集对象
将流转换为其余形式,coollect 方法做为终端操做, 接收一个Collector接口的实现,用于给Stream中元素作汇总的方法。最经常使用的方法,把流中全部元素收集到一个 List, Set 或 Collection 中排序
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.二、汇总
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,欢迎关注,转载请说明出处和做者。