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流上的操作,可以分成两种:
鸿蒙官方战略合作共建——HarmonyOS技术社区
Intermediate(中间操作): 中间操作的返回结果都是Stream,故可以多个中间操作叠加;
Terminal(终止操作): 终止操作用于返回我们最终需要的数据,只能有一个终止操作。
使用Stream流,可以清楚地知道我们要对一个数据集做何种操作,可读性强。而且可以很轻松地获取并行化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"}; Streamstrs1 = Stream.of(strs);//使用Stream中的静态方法:of() strs1.forEach(System.out::println);//打印输出(a、b、c、d) }
4.2 通过集合来生成
//通过集合来生成 static void gen2(){ Listlist = 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(){ Streamgenerate = Stream.generate(() -> 1);//使用Stream中的静态方法:generate() //limit 返回由该流的元素组成的流,截断长度不能超过maxSize generate.limit(10).forEach(System.out::println);//打印输出(打印10个1) }
4.4 通过Stream.iterate方法来创建
//使用iterator static void gen4() { Streamiterate = 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方法 Listlist = 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:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
Listlist = 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:求和
//求集合中的最大值 Listlist = 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:返回流中的任意元素
Listlist = 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
鸿蒙官方战略合作共建——HarmonyOS技术社区
Supplier supplier();创建一个结果容器A
BiConsumer
BinaryOperator combiner();函数接口,该参数的作用跟上一个方法(reduce)中的combiner参数一样,将并行流中各个子进程的运行结果(accumulator函数操作后的容器A)进行合并。
Function
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); Listlist = 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); Listlist = 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的方法摘要
修饰符和类型 | 方法和说明 |
---|---|
static | averagingDouble(ToDoubleFunction super T> mapper) 返回一个 Collector ,它产生应用于输入元素的双值函数的算术平均值。 |
static | averagingInt(ToIntFunction super T> mapper) 返回一个 Collector ,它产生应用于输入元素的整数值函数的算术平均值。 |
static | averagingLong(ToLongFunction super T> mapper) 返回一个 Collector ,它产生应用于输入元素的长值函数的算术平均值。 |
static | collectingAndThen(Collector |
static | counting() 返回 Collector类型的接受元件 T计数输入元件的数量。 |
static | groupingBy(Function super T,? extends K> classifier) 返回 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素,并且在返回的结果 Map 。 |
static | groupingBy(Function super T,? extends K> classifier, Collector super T,A,D> downstream) 返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。 |
static | groupingBy(Function super T,? extends K> classifier, Supplier |
static | groupingByConcurrent(Function super T,? extends K> classifier) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素。 |
static | groupingByConcurrent(Function super T,? extends K> classifier, Collector super T,A,D> downstream) 返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。 |
static | groupingByConcurrent(Function super T,? extends K> classifier, Supplier |
static Collector | joining() 返回一个 Collector ,按照遇到的顺序将输入元素连接到一个 String中。 |
static Collector | joining(CharSequence delimiter) 返回一个 Collector ,按照遇到的顺序连接由指定的分隔符分隔的输入元素。 |
static Collector | joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 返回一个 Collector ,它将按照指定的 Collector分隔的输入元素与指定的前缀和后缀进行连接。 |
static | mapping(Function super T,? extends U> mapper, Collector super U,A,R> downstream) 适应一个 Collector类型的接受元件 U至类型的一个接受元件 T通过积累前应用映射函数到每个输入元素。 |
static | maxBy(Comparator super T> comparator) 返回一个 Collector ,它根据给出的 Comparator产生最大元素,描述为 Optional |
static | minBy(Comparator super T> comparator) 返回一个 Collector ,根据给出的 Comparator产生最小元素,描述为 Optional |
static | partitioningBy(Predicate super T> predicate) 返回一个 Collector ,根据Predicate对输入元素进行 Predicate ,并将它们组织成 Map |
static | partitioningBy(Predicate super T> predicate, Collector super T,A,D> downstream) 返回一个 Collector ,它根据Predicate对输入元素进行 Predicate ,根据另一个 Collector减少每个分区的值,并将其组织成 Map |
static | reducing(BinaryOperator |
static | reducing(T identity, BinaryOperator |
static | reducing(U identity, Function super T,? extends U> mapper, BinaryOperator op) 返回一个 Collector ,它在指定的映射函数和 BinaryOperator下执行其输入元素的 BinaryOperator 。 |
static | summarizingDouble(ToDoubleFunction super T> mapper) 返回一个 Collector , double生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。 |
static | summarizingInt(ToIntFunction super T> mapper) 返回一个 Collector , int生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。 |
static | summarizingLong(ToLongFunction super T> mapper) 返回一个 Collector , long生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。 |
static | summingDouble(ToDoubleFunction super T> mapper) 返回一个 Collector ,它产生应用于输入元素的双值函数的和。 |
static | summingInt(ToIntFunction super T> mapper) 返回一个 Collector ,它产生应用于输入元素的整数值函数的和。 |
static | summingLong(ToLongFunction super T> mapper) 返回一个 Collector ,它产生应用于输入元素的长值函数的和。 |
static | toCollection(Supplier |
static | toConcurrentMap(Function super T,? extends K> keyMapper, Function super T,? extends U> valueMapper) 返回一个并发的 Collector ,它将元素累加到 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。 |
static | toConcurrentMap(Function super T,? extends K> keyMapper, Function super T,? extends U> valueMapper, BinaryOperator mergeFunction) 返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将提供的映射函数应用于输入元素的结果。 |
static | Collector |
static | toList() 返回一个 Collector ,它将输入元素 List到一个新的 List 。 |
static | toMap(Function super T,? extends K> keyMapper, Function super T,? extends U> valueMapper) 返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。 |
static | toMap(Function super T,? extends K> keyMapper, Function super T,? extends U> valueMapper, BinaryOperator mergeFunction) 返回一个 Collector ,它将元素累加到 Map ,其键和值是将提供的映射函数应用于输入元素的结果。 |
static | toMap(Function super T,? extends K> keyMapper, Function super T,? extends U> valueMapper, BinaryOperator mergeFunction, Supplier |
static | 返回一个 Collector ,将输入元素 Set到一个新的 Set 。 |
七、总结
对于Java中新特性除了 Stream 还有lamaba表达式都是可以帮忙我们很好的去优化代码,使我们的代码简洁且意图明确,避免繁琐的重复性的操作,对于文中有兴趣的小伙伴可以操作起来。
到此,相信大家对“JDK中Stream代码简洁的新特性介绍”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
当前文章:JDK中Stream代码简洁的新特性介绍
标题网址:http://scjbc.cn/article/pjspsd.html