快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

JDK中Stream代码简洁的新特性介绍

本篇内容主要讲解“JDK中Stream代码简洁的新特性介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JDK中Stream代码简洁的新特性介绍”吧!

目前创新互联公司已为近千家的企业提供了网站建设、域名、网站空间、网站托管维护、企业网站设计、润州网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

一、概述

Stream 是一组用来处理数组、集合的API,Stream API 提供了一种高效且易于使用的处理数据的方式。Java 8 中之所以费这么大的功夫引入  函数式编程 ,原因有两个:

代码简洁函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。

多核友好,Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是用用一下parallel()方法

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作

二、Stream特性

1、不是数据结构,没有内部存储,不会保存数据,故每个Stream流只能使用一次 2、不支持索引访问 3、支持并行  4、很容易生成数据或集合(List,Set) 5、支持过滤、查找、转换、汇总、聚合等操作  6、延迟计算,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算

三、分类

关于应用在Stream流上的操作,可以分成两种:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. Intermediate(中间操作): 中间操作的返回结果都是Stream,故可以多个中间操作叠加;

  3. Terminal(终止操作): 终止操作用于返回我们最终需要的数据,只能有一个终止操作。

使用Stream流,可以清楚地知道我们要对一个数据集做何种操作,可读性强。而且可以很轻松地获取并行化Stream流,不用自己编写多线程代码,可以让我们更加专注于业务逻辑。

JDK中Stream代码简洁的新特性介绍

无状态: 指元素的处理不受之前元素的影响;有状态: 指该操作只有拿到所有元素之后才能继续下去。非短路操作:  指必须处理所有元素才能得到最终结果;短路操作: 指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。

四、Stream的创建

1、通过数组来生成 2、通过集合来生成 3、通过Stream.generate方法来创建 4、通过Stream.iterate方法来创建  5、其他Api创建

4.1 通过数组来生成

//通过数组来生成    static void gen1(){        String[] strs = {"a","b","c","d"};        Stream strs1 = Stream.of(strs);//使用Stream中的静态方法:of()        strs1.forEach(System.out::println);//打印输出(a、b、c、d)    }

4.2 通过集合来生成

//通过集合来生成     static void gen2(){         List list = Arrays.asList("1","2","3","4");         Stream stream = list.stream();//获取一个顺序流         stream.forEach(System.out::println);//打印输出(1,2,3,4)     }

4.3 通过Stream.generate方法来创建

//generate static void gen3(){     Stream generate = Stream.generate(() -> 1);//使用Stream中的静态方法:generate()     //limit 返回由该流的元素组成的流,截断长度不能超过maxSize     generate.limit(10).forEach(System.out::println);//打印输出(打印10个1) }

4.4 通过Stream.iterate方法来创建

//使用iterator static void gen4() {     Stream iterate = Stream.iterate(1, x -> x + 1);//使用Stream中的静态方法:iterate()     iterate.limit(10).forEach(System.out::println);//打印输出(1,2,3,4,5,6,7,8,9,10) }

4.5其他Api创建

//其他方式     static void gen5(){         String str = "abcdefg";         IntStream stream =str.chars();//获取str 字节码         stream.forEach(System.out::println);//打印输出(97,98,99,100,101,102,103)     }

五、Stream的常用API

5.1 中间操作

1. filter:过滤流中的某些元素

//中间操作:如果调用方法之后返回的结果是Stream对象就意味着是一个中间操作  Arrays.asList(1,2,3,4,5).stream()//获取顺序流  .filter((x)->x%2==0) // 2 4   .forEach(System.out::println);  //求出结果集中所有偶数的和 int count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream()//获取顺序流 .filter(x -> x % 2 == 0).// 2 4 6 8  mapToInt(x->x).sum();//求和 System.out.println(count); //打印输出 20

2. distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素

Arrays.asList(1,2,3,3,3,4,5,2).stream()//获取顺序流  .distinct()//去重  .forEach(System.out::println);// 打印输出(1,2,3,4,5)  System.out.println("去重:---------------");  Arrays.asList(1,2,3,3,3,4,5,2).stream()//获取顺序流  .collect(Collectors.toSet())//Set()去重  .forEach(System.out::println);// 打印输出(1,2,3,4,5)

3. 排序

sorted():返回由此流的元素组成的流,根据自然顺序排序。sorted(Comparator com):返回由该流的元素组成的流,根据提供的  Comparator进行排序。

//获取最大值和最小值但是不使用min和max方法    List list = Arrays.asList(1,2, 3,4, 5, 6);    Optional min = list.stream().sorted().findFirst();//自然排序 根据数字从小到大排列    System.out.println(min.get());//打印输出(1)        Optional max2 = list.stream().sorted((a, b) -> b - a).findFirst();//定时排序 根据最大数进行排序    System.out.println(max2.get());//打印输出(6)   //按照大小(a-z)排序  Arrays.asList("java","c#","python","scala").stream().sorted().forEach(System.out::println);  //按照长度排序  Arrays.asList("java","c#","python","scala").stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println);

4. 截取

limit(n):返回由此流的元素组成的流,截短长度不能超过 nskip(n):在丢弃流的第n元素后,配合limit(n)可实现分页

//打印20-30这样的集合数据       Stream.iterate(1,x->x+1).limit(50)// limit 50 总共到50       .skip(20)// 跳过前 20       .limit(10) // 打印10个       .forEach(System.out::println);//打印输出(21,22,23,24,25,26,27,28,29,30)

5. 转换

map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

List list = Arrays.asList("a,b,c", "1,2,3");   //将每个元素转成一个新的且不带逗号的元素 Stream s1 = list.stream().map(s -> s.replaceAll(",", "")); s1.forEach(System.out::println); // abc  123   Stream s3 = list.stream().flatMap(s -> {     //将每个元素转换成一个stream     String[] split = s.split(",");     Stream s2 = Arrays.stream(split);     return s2; }); s3.forEach(System.out::println); // a b c 1 2 3

6. 消费

peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。

//将str中的每一个数值都打印出来,同时算出最终的求和结果 String str ="11,22,33,44,55";       System.out.println(Stream.of(str.split(",")).peek(System.out::println).mapToInt(Integer::valueOf).sum());//11 22 33 44 55 165

5.2 终止操作

1. 循环:forEach

Users类:

import java.util.Date;  /**  * @program: lambda  * @ClassName Users  * @description:  * @author: muxiaonong  * @create: 2020-10-24 11:00  * @Version 1.0  **/ public class Users {      private String name;     public Users() {}      /**      * @param name      */     public Users(String name) {         this.name = name;     }      /**      * @param name      * @return      */     public static Users build(String name){         Users u = new Users();         u.setName(name);         return u;     }      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      @Override     public String toString() {         return  "name='" + name + '\'';     }   }
//创建一组自定义对象 String str2 = "java,scala,python"; Stream.of(str2.split(",")).map(x->new Users(x)).forEach(System.out::println);//打印输出(name='java' name='scala' name='python') Stream.of(str2.split(",")).map(Users::new).forEach(System.out::println);//打印输出(name='java' name='scala' name='python') Stream.of(str2.split(",")).map(x->Users.build(x)).forEach(System.out::println);//打印输出(name='java' name='scala' name='python') Stream.of(str2.split(",")).map(Users::build).forEach(System.out::println);//打印输出(name='java' name='scala' name='python')

2. 计算:min、max、count、sum

min:返回流中元素最小值max:返回流中元素最大值count:返回流中元素的总个数sum:求和

//求集合中的最大值 List list = Arrays.asList(1,2, 3,4, 5, 6);  Optional max = list.stream().max((a, b) -> a - b);  System.out.println(max.get()); // 6   //求集合的最小值  System.out.println(list.stream().min((a, b) -> a-b).get()); // 1 //求集合的总个数 System.out.println(list.stream().count());//6  //求和  String str ="11,22,33,44,55";  System.out.println(Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum());  System.out.println(Stream.of(str.split(",")).mapToInt(Integer::valueOf).sum());  System.out.println(Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x -> x).sum());  System.out.println(Stream.of(str.split(",")).map(Integer::valueOf).mapToInt(x -> x).sum());

3. 匹配:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny

anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回falseallMatch:接收一个  Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回falsenoneMatch:接收一个 Predicate  函数,当流中每个元素都不符合该断言时才返回true,否则返回falsefindFirst:返回流中第一个元素findAny:返回流中的任意元素

List list = Arrays.asList(1,2, 3,4, 5, 6); System.out.println(list.stream().allMatch(x -> x>=0)); //如果集合中的元素大于等于0 返回true System.out.println(list.stream().noneMatch(x -> x > 5));//如果集合中的元素有大于5的元素。返回false System.out.println(list.stream().anyMatch(x -> x > 4));//如果集合中有大于四4的元素,返回true //取第一个偶数 Optional first = list.stream().filter(x -> x % 10 == 6).findFirst(); System.out.println(first.get());// 6 //任意取一个偶数 Optional any = list.stream().filter(x -> x % 2 == 0).findAny(); System.out.println(any.get());// 2

4.收集器:toArray、collect

collect:接收一个Collector实例,将流中元素收集成另外一个数据结构Collector

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. Supplier supplier();创建一个结果容器A

  3. BiConsumer

  4. BinaryOperator  combiner();函数接口,该参数的作用跟上一个方法(reduce)中的combiner参数一样,将并行流中各个子进程的运行结果(accumulator函数操作后的容器A)进行合并。

  5. Function

  6. Set

    characteristics();返回一个不可变的Set集合,用来表明该Collector的特征
/**  * @program: lambda  * @ClassName Customer  * @description:  * @author: muxiaonong  * @create: 2020-10-24 11:36  * @Version 1.0  **/ public class Customer {      private String name;      private Integer age;      ...getset忽略 }  public static void main(String[] args) {         Customer c1 = new Customer("张三",10);         Customer c2 = new Customer("李四",20);         Customer c3 = new Customer("王五",10);          List list = Arrays.asList(c1,c2,c3);          //转成list         List ageList = list.stream().map(Customer::getAge).collect(Collectors.toList());         System.out.println("ageList:"+ageList);//ageList:[10, 20, 10]          //转成set         Set ageSet = list.stream().map(Customer::getAge).collect(Collectors.toSet());         System.out.println("ageSet:"+ageSet);//ageSet:[20, 10]  //转成map,注:key不能相同,否则报错         Map CustomerMap = list.stream().collect(Collectors.toMap(Customer::getName, Customer::getAge));         System.out.println("CustomerMap:"+CustomerMap);//CustomerMap:{李四=20, 张三=10, 王五=10}  //字符串分隔符连接         String joinName = list.stream().map(Customer::getName).collect(Collectors.joining(",", "(", ")"));         System.out.println("joinName:"+joinName);//joinName:(张三,李四,王五)  //聚合操作 //1.学生总数         Long count = list.stream().collect(Collectors.counting());         System.out.println("count:"+count);//count:3 //2.最大年龄 (最小的minBy同理)         Integer maxAge = list.stream().map(Customer::getAge).collect(Collectors.maxBy(Integer::compare)).get();         System.out.println("maxAge:"+maxAge);//maxAge:20  //3.所有人的年龄         Integer sumAge = list.stream().collect(Collectors.summingInt(Customer::getAge));         System.out.println("sumAge:"+sumAge);//sumAge:40  //4.平均年龄         Double averageAge = list.stream().collect(Collectors.averagingDouble(Customer::getAge));         System.out.println("averageAge:"+averageAge);//averageAge:13.333333333333334  //分组         Map> ageMap = list.stream().collect(Collectors.groupingBy(Customer::getAge));         System.out.println("ageMap:"+ageMap);//ageMap:{20=[com.mashibing.stream.Customer@20ad9418], 10=[com.mashibing.stream.Customer@31cefde0, com.mashibing.stream.Customer@439f5b3d]}   //分区 //分成两部分,一部分大于10岁,一部分小于等于10岁         Map> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));         System.out.println("partMap:"+partMap);  //规约         Integer allAge = list.stream().map(Customer::getAge).collect(Collectors.reducing(Integer::sum)).get();         System.out.println("allAge:"+allAge);//allAge:40       }
 public static void main(String[] args) {         Customer c1 = new Customer("张三",10);         Customer c2 = new Customer("李四",20);         Customer c3 = new Customer("王五",10);          List list = Arrays.asList(c1,c2,c3);          //转成list         List ageList = list.stream().map(Customer::getAge).collect(Collectors.toList());         System.out.println("ageList:"+ageList);//ageList:[10, 20, 10]          //转成set         Set ageSet = list.stream().map(Customer::getAge).collect(Collectors.toSet());         System.out.println("ageSet:"+ageSet);//ageSet:[20, 10]  //转成map,注:key不能相同,否则报错         Map CustomerMap = list.stream().collect(Collectors.toMap(Customer::getName, Customer::getAge));         System.out.println("CustomerMap:"+CustomerMap);//CustomerMap:{李四=20, 张三=10, 王五=10}  //字符串分隔符连接         String joinName = list.stream().map(Customer::getName).collect(Collectors.joining(",", "(", ")"));         System.out.println("joinName:"+joinName);//joinName:(张三,李四,王五)  //聚合操作 //1.学生总数         Long count = list.stream().collect(Collectors.counting());         System.out.println("count:"+count);//count:3 //2.最大年龄 (最小的minBy同理)         Integer maxAge = list.stream().map(Customer::getAge).collect(Collectors.maxBy(Integer::compare)).get();         System.out.println("maxAge:"+maxAge);//maxAge:20  //3.所有人的年龄         Integer sumAge = list.stream().collect(Collectors.summingInt(Customer::getAge));         System.out.println("sumAge:"+sumAge);//sumAge:40  //4.平均年龄         Double averageAge = list.stream().collect(Collectors.averagingDouble(Customer::getAge));         System.out.println("averageAge:"+averageAge);//averageAge:13.333333333333334  //分组         Map> ageMap = list.stream().collect(Collectors.groupingBy(Customer::getAge));         System.out.println("ageMap:"+ageMap);//ageMap:{20=[com.mashibing.stream.Customer@20ad9418], 10=[com.mashibing.stream.Customer@31cefde0, com.mashibing.stream.Customer@439f5b3d]}   //分区 //分成两部分,一部分大于10岁,一部分小于等于10岁         Map> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));         System.out.println("partMap:"+partMap);  //规约         Integer allAge = list.stream().map(Customer::getAge).collect(Collectors.reducing(Integer::sum)).get();         System.out.println("allAge:"+allAge);//allAge:40       }

六、Stream的方法摘要

修饰符和类型方法和说明
staticCollectoraveragingDouble(ToDoubleFunction mapper) 返回一个 Collector ,它产生应用于输入元素的双值函数的算术平均值。
staticCollectoraveragingInt(ToIntFunction mapper) 返回一个 Collector ,它产生应用于输入元素的整数值函数的算术平均值。
staticCollectoraveragingLong(ToLongFunction mapper) 返回一个 Collector ,它产生应用于输入元素的长值函数的算术平均值。
static CollectorcollectingAndThen(Collector downstream, Function finisher) 适应 Collector进行额外的整理转换。
staticCollectorcounting() 返回 Collector类型的接受元件 T计数输入元件的数量。
static Collector>>groupingBy(Function classifier) 返回 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素,并且在返回的结果 Map 。
static Collector>groupingBy(Function classifier, Collector downstream) 返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static >CollectorgroupingBy(Function classifier, SuppliermapFactory, Collector downstream) 返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static Collector>>groupingByConcurrent(Function classifier) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素。
static Collector>groupingByConcurrent(Function classifier, Collector downstream) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static > CollectorgroupingByConcurrent(Function classifier, SuppliermapFactory, Collector downstream) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。
static Collectorjoining() 返回一个 Collector ,按照遇到的顺序将输入元素连接到一个 String中。
static Collectorjoining(CharSequence delimiter) 返回一个 Collector ,按照遇到的顺序连接由指定的分隔符分隔的输入元素。
static Collectorjoining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 返回一个 Collector ,它将按照指定的 Collector分隔的输入元素与指定的前缀和后缀进行连接。
static Collectormapping(Function mapper, Collector downstream) 适应一个 Collector类型的接受元件 U至类型的一个接受元件 T通过积累前应用映射函数到每个输入元素。
staticCollector>maxBy(Comparator comparator) 返回一个 Collector ,它根据给出的 Comparator产生最大元素,描述为 Optional
staticCollector>minBy(Comparator comparator) 返回一个 Collector ,根据给出的 Comparator产生最小元素,描述为 Optional
staticCollector>>partitioningBy(Predicate predicate) 返回一个 Collector ,根据Predicate对输入元素进行 Predicate ,并将它们组织成 Map> 。
static Collector>partitioningBy(Predicate predicate, Collector downstream) 返回一个 Collector ,它根据Predicate对输入元素进行 Predicate ,根据另一个 Collector减少每个分区的值,并将其组织成 Map ,其值是下游缩减的结果。
staticCollector>reducing(BinaryOperatorop) 返回一个 Collector ,它在指定的 Collector下执行其输入元素的 BinaryOperator 。
staticCollectorreducing(T identity, BinaryOperatorop) 返回 Collector执行下一个指定的减少其输入元件的 BinaryOperator使用所提供的身份。
static Collectorreducing(U identity, Function mapper, BinaryOperator op) 返回一个 Collector ,它在指定的映射函数和 BinaryOperator下执行其输入元素的 BinaryOperator 。
staticCollectorsummarizingDouble(ToDoubleFunction mapper) 返回一个 Collector , double生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。
staticCollectorsummarizingInt(ToIntFunction mapper) 返回一个 Collector , int生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。
staticCollectorsummarizingLong(ToLongFunction mapper) 返回一个 Collector , long生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。
staticCollectorsummingDouble(ToDoubleFunction mapper) 返回一个 Collector ,它产生应用于输入元素的双值函数的和。
staticCollectorsummingInt(ToIntFunction mapper) 返回一个 Collector ,它产生应用于输入元素的整数值函数的和。
staticCollectorsummingLong(ToLongFunction mapper) 返回一个 Collector ,它产生应用于输入元素的长值函数的和。
static > CollectortoCollection(SuppliercollectionFactory) 返回一个 Collector ,按照遇到的顺序将输入元素累加到一个新的 Collection中。
static Collector>toConcurrentMap(Function keyMapper, Function valueMapper) 返回一个并发的 Collector ,它将元素累加到 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。
static Collector>toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) 返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将提供的映射函数应用于输入元素的结果。
static >Collector toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, SuppliermapSupplier) 返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。
staticCollector>toList() 返回一个 Collector ,它将输入元素 List到一个新的 List 。
static Collector>toMap(Function keyMapper, Function valueMapper) 返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。
static Collector>toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)  返回一个 Collector ,它将元素累加到 Map ,其键和值是将提供的映射函数应用于输入元素的结果。
static > CollectortoMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, SuppliermapSupplier) 返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。
staticCollector> toSet()返回一个 Collector ,将输入元素 Set到一个新的 Set 。

七、总结

对于Java中新特性除了 Stream  还有lamaba表达式都是可以帮忙我们很好的去优化代码,使我们的代码简洁且意图明确,避免繁琐的重复性的操作,对于文中有兴趣的小伙伴可以操作起来。

到此,相信大家对“JDK中Stream代码简洁的新特性介绍”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!


文章标题:JDK中Stream代码简洁的新特性介绍
本文地址:http://6mz.cn/article/pjspsd.html

其他资讯