首页

关于java8新特性全量的StreamApi操作分类代码示例说明

标签:stream     发布时间:2022-12-07   

一、Stream API分类介绍

8cd77c08959c4b63903aa845aeb2544b.png

二、代码示例

具体包含stream创建方式(test01方法)、Stream中间操作(test02方法)、终端操作(test03方法)

package com.xwood.demo.java8;@b@@b@public class Person  implements  Comparable{ @b@    public Person(String name, int age) {@b@        this.name = name;@b@        this.age = age;@b@    }@b@@b@    private  String  name;@b@    private  int age;@b@@b@    public String getName() {@b@        return name;@b@    }@b@@b@    public void setName(String name) {@b@        this.name = name;@b@    }@b@@b@    public int getAge() {@b@        return age;@b@    }@b@@b@    public void setAge(int age) {@b@        this.age = age;@b@    }@b@@b@@b@    @Override@b@    public int compareTo(Object o) {@b@        return 0;@b@    }@b@}
package com.xwood.demo.java8;@b@@b@import java.util.*;@b@import java.util.stream.Collectors;@b@import java.util.stream.IntStream;@b@import java.util.stream.Stream;@b@@b@public class StreamAPITest {@b@    //创建Stream@b@    public void test01() {@b@        //通过Collection提供的stream()和parallelStream()方法创建流@b@        List<String> list = new ArrayList<>();@b@        list.add("hello");@b@        list.add("world");@b@        //将list中的元素以"流元素"的形式,存放于Stream中@b@        Stream<String> strStream = list.stream();@b@        Stream<String> strParallelStream = list.parallelStream();@b@@b@        String[] strs = new String[]{"hello", "world"};@b@        //通过Arrays提供的stream()方法创建流@b@        Stream<String> strStreamWithOfArray = Arrays.stream(strs);@b@        //通过Stream类提供的of()、iterate()和generate()方法创建流@b@        Stream<String> strStreamWithOf = Stream.of(strs);@b@        //创建无限流0、100、200、300、……,但仅仅获取前5个元素@b@        Stream<Integer> strStreamWithIterate = Stream.iterate(0, (x) -> ++x).limit(5);@b@        //创建无限流(包含无限个UUID),但仅仅获取前3个@b@        Stream<UUID> uUidStreamWithGenerate = Stream.generate(UUID::randomUUID).limit(3);@b@        //创建IntStream流@b@        IntStream intStream = IntStream.of(new int[]{1, 2, 3});@b@@b@        System.out.println("test01------------------------------------");@b@    }@b@@b@    //转换Stream操作@b@    public void test02() {@b@        //----------------limit()操作-------------------------@b@        //产生以0开始偶数组成的流,并且只使用前5个数字@b@        Stream<Integer> stream = Stream.iterate(0, x -> x + 2).limit(5);@b@        System.out.println("limt(5),截取无限流中的前5个元素:");@b@        stream.forEach(x -> System.out.print(x + "\t"));@b@@b@      @b@//            注意:一个Stream对象只能被终端操作使用一次,而上述的forEach()就是一个终端操作(用于打印流中的各个元素)。@b@//            因此,后续如果还要使用Stream对象,就必须重新生成。@b@@b@          @b@        //----------------filter()操作-------------------------@b@     @b@//            对产生的流进行过滤filter操作:筛选出比5大的数字;@b@//            以下语句等价于stream.filter( (x)->x>5  ).forEach(   (x) -> System.out.println(x)  );@b@        @b@        Stream<Integer> stream1 = Stream.iterate(0, x -> x + 2).limit(5);@b@        System.out.println("\nfilter((x) -> x > 3),筛选无限流中,大于3的元素:");@b@        stream1.filter((x) -> x > 3).forEach(x -> System.out.print(x + "\t"));@b@        //----------------limit()操作-------------------------@b@        //一个 Stream 只可以使用一次@b@        Stream<Integer> stream2 = Stream.iterate(0, x -> x + 2).limit(5);@b@        System.out.println("\nskip(2),跳过无限流中的前2个元素:");@b@        stream2.skip(2).forEach(x -> System.out.print(x + "\t"));@b@@b@        //----------------distinct()操作-------------------------@b@        Stream<Integer> stream3 = Stream.of(1, 1, 2, 2, 3, 4);@b@        //删除流中重复的元素:如果流中元素为简单类型(8个基本类型+String),则distinct()会自动去重@b@        System.out.println("\ndistinct(),删除无限流中的重复元素(简单类型):");@b@        stream3.distinct().forEach(x -> System.out.print(x + "\t"));@b@@b@        //删除流中重复的元素:如果流中元素为对象类型,需要通过“重写hashCode()和equals()”来告诉来告诉程序什么样的对象可以作为同一个元素(例如,可以认为:当name和age相同时,就作为同一个对象)@b@        Person[] pers = new Person[]{new Person("zs", 23), new Person("zs", 23), new Person("ls", 24)};@b@        System.out.println("\ndistinct(),删除无限流中的重复元素(对象类型):");@b@        Stream.of(pers).distinct().forEach(x -> System.out.print(x + "\t"));@b@@b@        //----------------map()操作:将每个元素进行了一次映射操作(转换操作),因为是每个元素都有映射后的产物,所以是map()是一对一的。-------------------------@b@        //将Stream中的每个单词,转为与之对应的大写单词@b@        Stream<String> stream4 = Stream.of("hello", "world", "hello", "stream");@b@        System.out.println("\nmap(),将Stream中的每个单词转为大写:");@b@        stream4.map(str -> str.toUpperCase()).forEach(x -> System.out.print(x + "\t"));@b@@b@        //map常用于部分内容的提取:例如,从Stream的各个Person对象中提取出name属性@b@        Person[] pers5 = new Person[]{new Person("ww", 25), new Person("zl", 26), new Person("zs", 23), new Person("ls", 24)};@b@        Stream<Person> stream5 = Stream.of(pers5);@b@        System.out.println("\nmap(),提取各个Person中的name属性:");@b@        stream5.map(per -> per.getName()).forEach(x -> System.out.print(x + "\t"));@b@@b@        //----------------flatMap()操作-------------------------@b@        //将Stream中所有单词转为字母形式,并删除重复的字母。例如,将"ab","bc"转为"a","b","b","c",再删除一个重复的"b",最终显示"a","b","c"@b@        Stream<String> stream6 = Stream.of("hello", "world", "hello", "stream");@b@        System.out.println("\nflatMap(),打印所有字符串中出现的字母,要求不重复:");@b@        //将流中的每个字符串,都映射成为Stream<String[]>,即{"h","e","l","l","o"},{"w","o","r","l","d"},...,即每个流元素都是一个String数组@b@        stream6.map(str -> str.split(""))@b@                //将上一步map()后的产物,全部纳入到一个“容器”中,即{"h","e","l","l","o","w","o","r","l","d",..,"e","a","m"},注意此时只有一个数组。可以发现,flatMap()是将多个String数组,转为了一个String数组,因此是多对一的。@b@                .flatMap(str -> Arrays.stream(str))@b@                //对上一步flatMap()的产物去重@b@                .distinct().forEach(x -> System.out.print(x + "\t"));@b@@b@        @b@//            排序操作:@b@//                    在Stream中,可以使用sorted()或sorted(Comparator<T>)进行排序@b@//                1.如果调用sorted(),则使用的是Comparable排序;@b@//                 sorted()方法会调用排序元素所重写的comparator()方法,根据comparator()中的规则进行排序。@b@//                 例如,如果排序的是Person类型的元素,就需要先让Person实现则使用的是Comparable排序接口,并重写comparator()方法,如下@b@        @b@        //----------------内部排序sorted()操作-------------------------@b@        Person[] pers7 = new Person[]{new Person("ww", 25), new Person("zs", 23), new Person("ww", 22), new Person("ls", 24)};@b@        System.out.println("\nsorted(),使用Comparable中的comparator()方法,对流中的Person对象排序(按age从小到大):");@b@        Stream.of(pers7).sorted().forEach(System.out::println);@b@        //JDK提供的很多类(如String)自身已经实现了Comparable接口,因此可以直接对其进行sort()排序,如下:@b@@b@        String[] strs = new String[]{"bb", "cc", "aa", "dd"};@b@        System.out.println("\nsorted(),对流中的字符串进行排序(String自身实现了Comparable接口,可以按字典顺序排序):");@b@        Stream.of(strs).sorted().forEach(str -> System.out.print(str + "\t"));@b@@b@         @b@//                     2.如果调用sorted(Comparator<T>),则使用的是Comparator排序;@b@//                     sorted(Comparator<T>)方法会使用参数中Comparator接口的compare()方法进行排序。@b@          @b@        System.out.println("\nsorted(Comparator<T>),使用Comparator中的compare()方法,对流中的Person对象排序(按age从小到大):");@b@        Stream.of(pers7).sorted((a, b) -> Integer.compare(a.getAge(), b.getAge())).forEach(System.out::println);@b@@b@        //还可以使用sorted()或sorted(Comparator<T>)进行多次排序,例如:对流中的Person对象,先按name排序,如果name相同再按age排序,如下@b@        System.out.println("\nsorted(Comparator<T>),二次排序(先name,再age):");@b@        Stream.of(pers7).sorted((a, b) ->@b@        {@b@            if (!a.getName().equals(b.getName())) {//排序规则:先name,再age@b@                //调用String内部提供的比较方法@b@                return String.CASE_INSENSITIVE_ORDER.compare(a.getName(), b.getName());@b@            } else {@b@                //调用Integer提供的比较方法@b@                return Integer.compare(a.getAge(), b.getAge());@b@            }@b@        })@b@                .forEach(System.out::println);@b@@b@        System.out.println("test02------------------------------------");@b@    }@b@@b@    static Person[] pers = null;@b@@b@    static {@b@        pers = new Person[]{new Person("ww", 25), new Person("zl", 26), new Person("zl", 22), new Person("zs", 23), new Person("ls", 24)};@b@    }@b@@b@    //终端操作@b@    public void test03() {@b@        //判断是否全部人的age都大于24@b@        boolean result = Stream.of(pers).map(per -> per.getAge()).allMatch(age -> age > 24);@b@        System.out.println("allMatch():" + result);@b@@b@        //判断是否存在大于24的age (即只要有比24大的age即可)@b@        boolean result1 = Stream.of(pers).map(per -> per.getAge()).anyMatch(age -> age > 24);@b@        System.out.println("anyMatch():" + result1);@b@@b@        //判断是否没有age比24大(即不存在大于24的age)@b@        boolean result2 = Stream.of(pers).map(per -> per.getAge()).noneMatch(age -> age > 24);@b@        System.out.println("noneMatch():" + result2);@b@@b@        //获取流中第一个元素@b@        Optional<Integer> firstAge = Stream.of(pers).map(per -> per.getAge()).findFirst();@b@        System.out.println("firstAge():" + firstAge.get());@b@@b@        //获取流中任一个元素(不是随机一个元素,而是根据某个算法找到的一个元素;即:如果对同一个流多次进行findAny()操作,那么得到的将是同一个元素)@b@        Optional<Integer> certainAge = Stream.of(pers).map(per -> per.getAge()).findAny();@b@        System.out.println("findAny():" + certainAge.get());@b@@b@        //获取“最大”的元素。“最大”是由max(Comparator<T>)方法的参数约定@b@        Optional<Person> maxPerson = Stream.of(pers).max((a, b) -> a.getAge() > b.getAge() ? 1 : (a.getAge() < b.getAge() ? -1 : 0));@b@        System.out.println("max():" + maxPerson.get().getAge());@b@@b@        //reduce,聚合流中的所有元素:本次是将流中的全部age值,聚合为一个值(所有age之和)@b@        Integer reduceAge = Stream.of(pers).map(per -> per.getAge()).reduce(0, (a, b) -> a + b);@b@        System.out.println("reduce():" + reduceAge);@b@       @b@//    本程序中的reduce( 0,(a,b)->a+b )表示求和,类似于以下for()求和方式。其中,a相当于sum,b相当于i。@b@//    int sum = 0;@b@//    for(int i=0;i<100;i++){@b@//       sum += i ;@b@//    }@b@       @b@@b@        //求名字中s出现的次数@b@        Integer sCount = Stream.of(pers).map(per -> per.getName()).map(str -> str.split(""))@b@                .flatMap(str -> Arrays.stream(str))@b@                //先将每个字母映射数字0或1(如果是s,则映射为1;否则为0),再累加全部的数字(只有s才是有效的累加;因为其他字母是0,对0进行累加是没有效果的)@b@                .map(a -> a.equals("s") ? 1 : 0).reduce(0, (x, y) -> x + y);@b@        System.out.println("s出现的次数是:" + sCount);@b@@b@//        ----collect()聚合操作:将流的元素聚合成一个集合(或一个值)----- @b@        //聚合成一个List集合@b@        List<String> nameList = Arrays.stream(pers).map(per -> per.getName()).collect(Collectors.toList());@b@        System.out.println("collect(Collectors.toList():" + nameList);@b@@b@        //聚合成一个Map集合:实现按key分组(根据年龄分组)@b@        Map<Integer, List<Person>> ageMap = Arrays.stream(pers).collect(Collectors.groupingBy(Person::getAge));@b@        System.out.println("Collectors.groupingBy(Person::getAge):\n" + ageMap);@b@@b@        //聚合成一个Map集合:实现按key分区(根据age是否大于24)@b@        Map<Boolean, List<Integer>> agePartition = Arrays.stream(pers).map(Person::getAge).collect(Collectors.partitioningBy(age -> age > 24));@b@        System.out.println("Collectors.partitioningBy( age -> age>24 ):" + agePartition);@b@@b@        //聚合成一个值:求最小值(也可以是最大值、个数、求和等聚合计算)@b@        Optional<Integer> minAge = Arrays.stream(pers).map(per -> per.getAge()).collect(Collectors.minBy(Integer::min));@b@        System.out.println("Collectors.minBy(Integer::min):" + minAge);@b@@b@        //聚合成一个值:连接操作,将流中的多个值连接成一个字符串,并加上前缀和后缀。@b@        String allNameInOneStr = Arrays.stream(pers).map(Person::getName).collect(Collectors.joining(",", "**prefix**", "**suffix**"));@b@        System.out.println("Collectors.joining(...)" + allNameInOneStr);@b@@b@        System.out.println("test03------------------------------------");@b@    }@b@@b@@b@    public static void main(String[] args) {@b@      new StreamAPITest().test01() ;@b@      new StreamAPITest().test02() ;@b@        new StreamAPITest().test03();@b@    }@b@}

控制台运行结果

test01------------------------------------@b@limt(5),截取无限流中的前5个元素:@b@0	2	4	6	8	@b@filter((x) -> x > 3),筛选无限流中,大于3的元素:@b@4	6	8	@b@skip(2),跳过无限流中的前2个元素:@b@4	6	8	@b@distinct(),删除无限流中的重复元素(简单类型):@b@1	2	3	4	@b@distinct(),删除无限流中的重复元素(对象类型):@b@com.xwood.demo.java8.Person@16b98e56	com.xwood.demo.java8.Person@7ef20235	com.xwood.demo.java8.Person@27d6c5e0	@b@map(),将Stream中的每个单词转为大写:@b@HELLO	WORLD	HELLO	STREAM	@b@map(),提取各个Person中的name属性:@b@ww	zl	zs	ls	@b@flatMap(),打印所有字符串中出现的字母,要求不重复:@b@h	e	l	o	w	r	d	s	t	a	m	@b@sorted(),使用Comparable中的comparator()方法,对流中的Person对象排序(按age从小到大):@b@com.xwood.demo.java8.Person@7291c18f@b@com.xwood.demo.java8.Person@34a245ab@b@com.xwood.demo.java8.Person@7cc355be@b@com.xwood.demo.java8.Person@6e8cf4c6@b@@b@sorted(),对流中的字符串进行排序(String自身实现了Comparable接口,可以按字典顺序排序):@b@aa	bb	cc	dd	@b@sorted(Comparator<T>),使用Comparator中的compare()方法,对流中的Person对象排序(按age从小到大):@b@com.xwood.demo.java8.Person@7cc355be@b@com.xwood.demo.java8.Person@34a245ab@b@com.xwood.demo.java8.Person@6e8cf4c6@b@com.xwood.demo.java8.Person@7291c18f@b@@b@sorted(Comparator<T>),二次排序(先name,再age):@b@com.xwood.demo.java8.Person@6e8cf4c6@b@com.xwood.demo.java8.Person@7cc355be@b@com.xwood.demo.java8.Person@7291c18f@b@com.xwood.demo.java8.Person@34a245ab@b@test02------------------------------------@b@allMatch():false@b@anyMatch():true@b@noneMatch():false@b@firstAge():25@b@findAny():25@b@max():26@b@reduce():120@b@s出现的次数是:2@b@collect(Collectors.toList():[ww, zl, zl, zs, ls]@b@Collectors.groupingBy(Person::getAge):@b@{22=[com.xwood.demo.java8.Person@238e0d81], 23=[com.xwood.demo.java8.Person@31221be2], 24=[com.xwood.demo.java8.Person@377dca04], 25=[com.xwood.demo.java8.Person@728938a9], 26=[com.xwood.demo.java8.Person@21b8d17c]}@b@Collectors.partitioningBy( age -> age>24 ):{false=[22, 23, 24], true=[25, 26]}@b@Collectors.minBy(Integer::min):Optional[24]@b@Collectors.joining(...)**prefix**ww,zl,zl,zs,ls**suffix**@b@test03------------------------------------@b@@b@Process finished with exit code 0