Java8实战之Stream流式操作

简介

Java8中有两大最为重要的改变。第一个是Lambda 表达式;另外一个则是Stream API(java.util.stream.*)
StreamJava8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL 执行的数据库查询。也可以使用Stream API来并行执行操作。简而言之,Stream API提供了一种高效且易于使用的处理数据的方式。

Stream(流)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算!”

注意:
1.Stream 自己不会存储元素。
2. Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
3. Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

Stream操作步骤

  1. 创建Stream:一个数据源(如:集合、数组),获取一个流
  2. 中间操作:一个中间操作链,对数据源的数据进行处理
  3. 终止操作(终端操作):一个终止操作,执行中间操作链,并产生结果

流程如下图所示:
在这里插入图片描述

创建Stream

方式一:Java8 中的Collection 接口被扩展,提供了两个获取流的方法:

  • default Stream<E> stream(): 返回一个顺序流
  • default Stream<E> parallelStream() : 返回一个并行流
// 1、 通过Collection集合提供的stream()或parallelStream()
List<String> list = new ArrayList<>();
// stream()
Stream<String> stream1 = list.stream();
// parallelStream()
Stream<String> parallelStream = list.parallelStream();

方式二:通过Arrays中的静态方法stream()获取数组流

// 2、通过Arrays中的静态方法stream()获取数组流
String[] strArray = {"1","2"};
Stream<String> stream2 = Arrays.stream(strArray);

方式三:通过stream类中的静态方法of(),它可以接收任意数量的参数

// 通过stream类中的静态方法of()
Stream<String> stream3 = Stream.of("1", "2");

方式四:创建无限流,可以使用静态方法Stream.iterate()Stream.generate(), 创建无限流

// 4、创建无限流
// 使用迭代
Stream<Integer> iterateStream = Stream.iterate(0, (e) -> e + 2);
iterateStream.limit(10).forEach(System.out::println);

// 使用生成
Stream<Double> generateStream = Stream.generate(() -> Math.random());
generateStream.limit(10).forEach(System.out::println);

Stream的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值

筛选与切片:

 /**
  * 切片与筛选
  *
  * filter(Predicatep):接收Lambda ,从流中排除某些元素。
  * limit(long maxSize):截断流,使其元素不超过给定数量。
  * skip(long n):跳过元素,返回一个扔掉了前n 个元素的流。若流中
  * distinct():筛选,通过流所生成元素的hashCode() 和equals() 去除重复元素
  */
 @Test
 public void test2(){
     // 中间操作:不会执行任何操作
     Stream<User> userStream = userList.stream().filter((e) -> {
         System.out.println("stream 中间操作");
         return e.getAge() > 20;
     });

     // 终止操作:一次性执行完全部内容,称为"惰性求值"
     userStream.forEach(System.out::println);
 }

 // limit(long maxSize):截断流,使其元素不超过给定数量
 @Test
 public void test3(){
     userList.stream().limit(2).forEach(System.out::println);
 }


 // skip(long n):跳过元素,返回一个扔掉了前n 个元素的流。若流中
 @Test
 public void test4(){
     userList.stream().skip(2).forEach(System.out::println);

 }

 // distinct():筛选,通过流所生成元素的hashCode() 和equals() 去除重复元素
 @Test
 public void test5(){
     userList.stream().distinct().forEach(System.out::println);
 }

映射:

/**
  * 映射
  *
  *
  * map(Functionf):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  * flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
  */
 // map(Functionf):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
 @Test
 public void test6(){
     userList.stream().map(User::getName).forEach(System.out::println);
 }

 // flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
 @Test
 public void test7() {
     List<String> list = Arrays.asList("a a", "c c", "d d", "b b");
     Stream<String> stringStream = list.stream().flatMap(e -> Arrays.stream(e.split(" ")));
     stringStream.forEach(System.out::println);
 }

排序:

/**
  * 排序
  *
  * sorted():产生一个新流,其中按自然顺序排序
  * sorted(Comparatorcomp):产生一个新流,其中按比较器顺序排序
  */

 // sorted():产生一个新流,其中按自然顺序排序
 @Test
 public void test8(){
     List<String> list = Arrays.asList("a a", "c c", "d d", "b b");
     list.stream().sorted().forEach(System.out::println);
 }

 // sorted(Comparatorcomp):产生一个新流,其中按比较器顺序排序
 @Test
 public void test9(){
    userList.stream().sorted((e1,e2) -> {
        if(e1.getAge() > e2.getAge()){
             return 1;
        }
        return 0;
    }).forEach(System.out::println);
 }

Stream的终止操作

查找与匹配:

/**
  * 查找与匹配
  *
  * allMatch(Predicate p):检查是否匹配所有元素
  * anyMatch(Predicate p): 检查是否至少匹配一个元素
  * noneMatch(Predicatep):检查是否没有匹配所有元素
  * findFirst():返回第一个元素
  * findAny():返回当前流中的任意元素
  * count():返回流中元素总数
  * max(Comparatorc):返回流中最大值
  * min(Comparatorc):返回流中最小值
  * forEach(Consumerc):内部迭代(使用Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了)
  */
 // allMatch(Predicate p):检查是否匹配所有元素
 @Test
 public void test10() {
     boolean b = userList.stream().allMatch((e) -> "男".equals(e.getGender()));
     System.out.println("allMatch:" + b);
 }

 // anyMatch(Predicate p): 检查是否至少匹配一个元素
 @Test
 public void test11(){
     boolean b = userList.stream().anyMatch((e) -> "男".equals(e.getGender()));
     System.out.println("anyMatch:" + b);
 }

 // noneMatch(Predicatep):检查是否没有匹配所有元素
 @Test
 public void test12(){
     boolean b = userList.stream().noneMatch((e) -> "男".equals(e.getGender()));
     System.out.println("noneMatch:" + b);
 }

 // findFirst():返回第一个元素
 @Test
 public void test13(){
     Optional<User> first = userList.stream().findFirst();
     System.out.println(first.get());
 }

 // findAny():返回当前流中的任意元素
 @Test
 public void test14(){
     Optional<User> any = userList.stream().findAny();
     System.out.println(any.get());
 }

 // count():返回流中元素总数
 @Test
 public void test15(){
     long count = userList.stream().count();
     System.out.println(count);
 }

 // max(Comparatorc):返回流中最大值
 @Test
 public void test16(){
     Optional<User> max = userList.stream().max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
     System.out.println(max.get());
 }

 // min(Comparatorc):返回流中最小值
 @Test
 public void test17(){
     Optional<User> max = userList.stream().min((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
     System.out.println(max.get());
 }

 // forEach(Consumerc):内部迭代(使用Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了)
 @Test
 public void test18(){
     userList.stream().forEach(System.out::println);
 }

规约:

/**
  * 规约
  *
  * reduce(T iden, BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回T
  * reduce(BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回Optional<T>
  */
 // reduce(T iden, BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回T
 @Test
 public void test19() {
     List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
     Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
     System.out.println(reduce);
 }

 // reduce(BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回Optional<T>
 @Test
 public void test20(){
     Optional<Integer> reduce = userList.stream().map(User::getAge).reduce(Integer::sum);
     System.out.println(reduce.get());
 }

收集:

/**
  * 收集
  *
  * collect(Collector c):将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
  *
  */
 @Test
 public void test21() {
     // toList
     List<User> list = userList.stream().collect(Collectors.toList());
     list.forEach(System.out::println);

     System.out.println("-----------------------");

     // toSet
     Set<User> userSet = userList.stream().collect(Collectors.toSet());
     userSet.forEach(System.out::println);

     System.out.println("-----------------------");

     // 计算流中元素的个数
     Long count = userList.stream().collect(Collectors.counting());
     System.out.println(count);

     System.out.println("-----------------------");

     // 平均值
     Double avg = userList.stream().collect(Collectors.averagingDouble(User::getAge));
     System.out.println(avg);

     System.out.println("-----------------------");

     // 总和
     Double sum = userList.stream().collect(Collectors.summingDouble(User::getAge));
     System.out.println(sum);

     System.out.println("-----------------------");

     // 最大值
     Optional<User> max = userList.stream().collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));
     System.out.println(max.get());

     System.out.println("-----------------------");

     // 最小值
     Optional<Integer> min = userList.stream().map(User::getAge).collect(Collectors.minBy(Integer::compare));
     System.out.println(min);

     System.out.println("-----------------------");

     // 分组
     Map<String, List<User>> group = userList.stream().collect(Collectors.groupingBy(User::getGender));
     System.out.println(group);

     System.out.println("-----------------------");

     // 多级分组
     Map<String, Map<Integer, List<User>>> multilevelGroup = userList.stream().collect(Collectors.groupingBy(User::getGender, Collectors.groupingBy(User::getAge)));
     System.out.println(multilevelGroup);

     System.out.println("-----------------------");

     // 根据true或false进行分区
     Map<Boolean, List<User>> area = userList.stream().collect(Collectors.partitioningBy((e) -> e.getGender().equals("男")));
     System.out.println(area);

     System.out.println("-----------------------");

     // 求统计值
     DoubleSummaryStatistics summaryStatistics = userList.stream().collect(Collectors.summarizingDouble(User::getAge));
     System.out.println(summaryStatistics.getMax());
     System.out.println(summaryStatistics.getMin());
     System.out.println(summaryStatistics.getCount());
     System.out.println(summaryStatistics.getAverage());

     System.out.println("-----------------------");

     // 连接字符串
     String joining = userList.stream().map(User::getName).collect(Collectors.joining());
     System.out.println(joining);

     System.out.println("-----------------------");

     // 连接字符串,按符号分隔
     String joiningSp = userList.stream().map(User::getName).collect(Collectors.joining(","));
     System.out.println(joiningSp);

     // 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值
     Integer reducing = userList.stream().collect(Collectors.reducing(0, User::getAge, Integer::sum));
     System.out.println(reducing);

     // 包裹另一个收集器,对其结果转换函数
     Integer collectingAndThen = userList.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
     System.out.println(collectingAndThen);
}
  • 12
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值