• 【java】集合流式编程总结


    在具体的介绍之前,先总结一波常用的写法,有基础的可以直接拿来用,没有基础的可以先跳过,看完下面的基础再回来看

    List<User> userList = new ArrayList<>();
        userList.addAll(Arrays.asList(
            new User(1, 11, "张三"),
            new User(1, 11, "张三"),
            new User(2, 22, "李四"),
            new User(1, 33, "王五"),
            new User(2, 44, "赵六"),
            new User(2, 44, "赵六")));
        //----------------------------------------------中间操作----------------------------------------------
        //【filter】从列表中筛选出性别为女的数据
        List<User> filterUsage = userList.stream().filter(s->s.getSex() == 2).collect(Collectors.toList());
        //结果:[User(sex=2, age=22, name=李四), User(sex=2, age=44, name=赵六), User(sex=2, age=44, name=赵六)]
        System.out.println(filterUsage);
        //【distinct】从列表中去重
        List<User> distinctUsage = userList.stream().distinct().collect(Collectors.toList());
        //结果:[User(sex=1, age=11, name=张三), User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=赵六)]
        System.out.println(distinctUsage);
        //【sorted】按照年龄字段从大到小重新排序 (从小到大就是s1.getAge()-s2.getAge())
        List<User> sortedUsage = userList.stream().sorted((s1,s2)->s2.getAge()-s1.getAge()).collect(Collectors.toList());
        //结果:[User(sex=2, age=44, name=赵六), User(sex=2, age=44, name=赵六), User(sex=1, age=33, name=王五), User(sex=2, age=22, name=李四), User(sex=1, age=11, name=张三), User(sex=1, age=11, name=张三)]
        System.out.println(sortedUsage);
        //【limit】获取前两条数据
        List<User> limitUsage = userList.stream().limit(2).collect(Collectors.toList());
        //结果:[User(sex=1, age=11, name=张三), User(sex=1, age=11, name=张三)]
        System.out.println(limitUsage);
        //【skip】跳过前两条,之后获取前三条数据
        List<User> skipUsage = userList.stream().skip(2).limit(3).collect(Collectors.toList());
        //结果:[User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=赵六)]
        System.out.println(skipUsage);
        //【map】获取所有人的姓名
        List<String> mapUsage = userList.stream().map(User::getName).collect(Collectors.toList());
        //结果:[张三, 张三, 李四, 王五, 赵六, 赵六]
        System.out.println(mapUsage);
        //【flatMap】
    
        //【Collectors工具类一些常用方法】
        //【groupingBy】分组
        // 将集合中的数据按照姓名分组
        Map<String, List<User>> groupingByUsage = userList.stream().collect(Collectors.groupingBy(s -> s.getName()));
        //结果:{李四=[User(sex=2, age=22, name=李四)], 张三=[User(sex=1, age=11, name=张三), User(sex=1, age=11, name=张三)],
        //      王五=[User(sex=1, age=33, name=王五)], 赵六=[User(sex=2, age=44, name=赵六), User(sex=2, age=44, name=赵六)]}
        System.out.println(groupingByUsage);
        // 将集合中的数据按照姓名+性别分组
        Map<String, List<User>> groupingByUsage2 = userList.stream().collect(Collectors.groupingBy(s -> s.getName() + "#" + s.getSex()));
        //结果:{张三#1=[User(sex=1, age=11, name=张三), User(sex=1, age=11, name=张三)], 李四#2=[User(sex=2, age=22, name=李四)],
        //      赵六#2=[User(sex=2, age=44, name=赵六), User(sex=2, age=44, name=赵六)], 王五#1=[User(sex=1, age=33, name=王五)]}
        System.out.println(groupingByUsage2);
        //【maxBy】获取集合中年龄最大的对象信息
        User maxByUsage = userList.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get();
        //结果:User(sex=2, age=44, name=赵六)
        System.out.println(maxByUsage);
        //【minBy】获取集合中年龄最小的对象信息
        User minByUsage = userList.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge())).get();
        //结果:User(sex=1, age=11, name=张三)
        System.out.println(minByUsage);
        //【joining】拼接集合中所有的用户名称---直接拼接
        String joiningUsage = userList.stream().map(User::getName).collect(Collectors.joining());
        //结果:张三张三李四王五赵六赵六
        System.out.println(joiningUsage);
        //拼接中间加上逗号
        String joiningUsage2 = userList.stream().map(User::getName).collect(Collectors.joining(","));
        //结果:张三,张三,李四,王五,赵六,赵六
        System.out.println(joiningUsage2);
        //拼接中间加上逗号,两边加上前后缀
        String joiningUsage3 = userList.stream().map(User::getName).collect(Collectors.joining(",","[","]"));
        //结果:[张三,张三,李四,王五,赵六,赵六]
        System.out.println(joiningUsage3);
        //【counting】获取集合中对象的数量
        Long countingUsage = userList.stream().collect(Collectors.counting());
        //结果:6
        System.out.println(countingUsage);
        //【summingInt】获取集合中所有对象年龄的和
        int summingIntUsage = userList.stream().collect(Collectors.summingInt(User::getAge));
        //结果:165
        System.out.println(summingIntUsage);
        //【averagingInt】获取集合中所有对象年龄的平均值
        Double averagingIntUsage = userList.stream().collect(Collectors.averagingInt(User::getAge));
        //结果:27.5
        System.out.println(averagingIntUsage);
        //【summarizingInt】获取集合中所有对象的数量/和/最大值/最小值/平均值等信息
        IntSummaryStatistics summarizingIntUsage = userList.stream().collect(Collectors.summarizingInt(User::getAge));
        //结果:IntSummaryStatistics{count=6, sum=165, min=11, average=27.500000, max=44}
        System.out.println(summarizingIntUsage);
    
        //----------------------------------------------最终操作----------------------------------------------
    
        //【collect】
        //这里不做演示,上面的所有例子中都有用到
        //【reduce】将集合中的所有性别字段的值按照相加的规则求乘积
        Integer reduceUsage = userList.stream().map(User::getSex).reduce((s1, s2) -> s1 * s2).get();
        //结果:8
        System.out.println(reduceUsage);
        //【count】求集合中对象的数量
        long countUsage = userList.stream().count();
        //结果:6
        System.out.println(countUsage);
        //【forEach】遍历出所有的对象的名称
        Consumer<String> action = System.out::println;
        //结果:张三 张三 李四 王五 赵六 赵六
        userList.stream().map(User::getName).forEach(action);
        //【max&min】获取集合中所有对象中年龄的最大值和最小值
        Integer maxUsage = userList.stream().map(User::getAge).max(Integer::compareTo).get();
        //结果:44
        System.out.println(maxUsage);
        Integer minUsage = userList.stream().map(User::getAge).min(Integer::compareTo).get();
        //结果:11
        System.out.println(minUsage);
        //【Matching -> allMatch、anyMatch、noneMatch】
        //allMatch:只有当流中所有的元素,都匹配指定的规则,才会返回true
        boolean allMatchUsage = userList.stream().map(User::getAge).allMatch(e -> e >= 44);
        //结果:false
        System.out.println(allMatchUsage);
        //anyMatch:只要流中有任意的数据,满足指定的规则,都会返回true
        boolean anyMatchUsage = userList.stream().map(User::getAge).anyMatch(e -> e <= 11);
        //结果:true
        System.out.println(anyMatchUsage);
        //noneMatch:只有当流中所有的元素,都不满足指定的规则,才会返回true
        boolean noneMatchUsage = userList.stream().map(User::getAge).noneMatch(e -> e < 11);
        //结果:true
        System.out.println(noneMatchUsage);
        //【find--> findFirst、findAny】【parallelStream并行流、stream串行流】
        //findFirst:从流中获取开头第一个元素
        User user = userList.stream().findFirst().get();
        //结果:User(sex=1, age=11, name=张三)
        System.out.println(user);
        User user2 = userList.parallelStream().findFirst().get();
        //结果:User(sex=1, age=11, name=张三)
        System.out.println(user2);
        //findAny:单线程是获取第一个元素,多线程可能不一样
        User user3 = userList.stream().findAny().get();
        //结果:User(sex=1, age=11, name=张三)
        System.out.println(user3);
        User user4 = userList.parallelStream().findAny().get();
        //结果:User(sex=1, age=33, name=王五)
        System.out.println(user4);
        //【IntStream+summaryStatistics】获取int数组中的最大值
        //1.准备一个int数组作为数据源
        int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        //2.读取数据到流中,获取IntStream对象
        IntStream intStream = Arrays.stream(array);
        //两种方法:(不能一起用,因为是中间操作)
        //1. 直接通过IntStream来获取
        //System.out.println(intStream.max().getAsInt());
        //2. 通过IntSummaryStatistics,里面包括最大/最小/平均/数量等方法
        IntSummaryStatistics intSummaryStatistics = intStream.summaryStatistics();
        //结果:9
        System.out.println(intSummaryStatistics.getMax());
    
        //----------------------------------------------其它操作----------------------------------------------
        //【list转数组1】
        Integer[] ints = userList.stream().map(User::getAge).toArray(Integer[]::new);
        //【list转数组2】
        List<String> list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
        String[] strings = list.toArray(new String[list.size()]);
        //【数组转list】
        String[] arrays = {"1", "2", "3"};
        List<String> listStrings = Stream.of(arrays).collect(Collectors.toList());
        //结果:[1, 2, 3]
        System.out.println(listStrings);
        //【修改集合中的对象属性的值】
        //原值:[User(sex=1, age=11, name=张三), User(sex=1, age=11, name=张三), User(sex=2, age=22, name=李四), 
        //      User(sex=1, age=33, name=王五), User(sex=2, age=44, name=赵六), User(sex=2, age=44, name=赵六)]
        System.out.println(userList);
        userList.forEach(s->{
            s.setAge(100);
            s.setSex(100);
        });
        //新值:[User(sex=100, age=100, name=张三), User(sex=100, age=100, name=张三),User(sex=100, age=100, name=李四), 
        // User(sex=100, age=100, name=王五), User(sex=100, age=100, name=赵六), User(sex=100, age=100, name=赵六)]
        System.out.println(userList);
    View Code

    、集合流的简介

    1. 集合的流式编程的简介

    Stream是JDK1.8之后出现的新特性,也是JDK1.8新特性中最值得学习的两种新特性之一(另一个是lambda表达式)Stream是对集合操作的增强,流不是集合的元素,不是一种数据结构,不负责数据的存储的。流更像是一个迭代器,可以单向的遍历一个集合中的每一个元素,并且不可循环。

    2. 为什么要使用集合的流式编程

    有些时候,对集合中的元素进行操作的时候,需要使用到其他操作的结果。在这个过程中,集合的流式编程可以大幅度的简化代码的数量。将数据源中的数据,读取到一个流中,可以对这个流中的数据进行操作(删除、过滤、映射...)。每次的操作结果也是一个流对象,可以对这个流再进行其它的操作。

    3. 使用流式编程的步骤

    通常情况下,对集合中的数据使用流式编程,需要经过以下三步:

     (1)获取数据源,将数据源中的数据读取到流中
     (2)对流中的数据进行各种各样的处理
     (3)对流中的数据进行整合处理

    在上述三个过程:

     (1)过程2中,有若干方法,可以对流中的数据进行各种各样的操作,并且返回流对象本身,这样的操作,被称为中间操作
     (2)过程3中,有若干方法,可以对流中的数据进行各种处理,并关闭流,这样的操作,被称为最终操作

    在中间操作和最终操作中,基本上所有的方法参数都是函数式接口,可以使用lambda表达式来实现。使用集合的流式编程,来简化代码量。

    二、数据源的获取

    1. 数据源的简介

    数据源,顾名思义,就是流中的数据的来源,是集合的流式编程的第一步,将数据源中的数据读取到流中,进行处理。注意:将数据读取到流中进行处理的时候,与数据源中的数据没有关系。也就是说,中间操作对流中的数据进行处理、过滤、映射、排序...是不会影响到数据源中的数据的。

    2. 数据源的获取

    这个过程,其实是将一个容器中的数据,读取到一个流中,因此无论什么容器作为数据源,读取到流中的方法返回值一定是一个Stream。

    public static void main(String[] args) throws Exception{
        //将集合作为数据源,读取集合中的数据到一个流中
        collectionDataSource();
        //将数组作为数据源,读取数组中的数据到一个流中(使用引用数据类型)
        arrayDataSource();
        //将数组作为数据源,读取数组中的数据到一个流中(使用基本数据类型)
    }
    
    //将集合作为数据源,读取集合中的数据到一个流中
    public static void collectionDataSource(){
        //1.实例化一个集合
        List<Integer> list = new ArrayList<>();
        //2.填充元素
        Collections.addAll(list,0,1,2,3,4,5,6,7,8,9);
        //3.读取集合中的数据,将其读取到流中
        //Stream<Integer> stream = list.stream();//同步流
        Stream<Integer> integerStream = list.parallelStream();//并发流
        //4.输出stream
        System.out.println(integerStream);//java.util.stream.ReferencePipeline$Head@4554617c
    }
    
    //将数组作为数据源,读取数组中的数据到一个流中
    public static void arrayDataSource(){
        //1.实例化一个数组
        Integer[] array = new Integer[]{0,1,2,3,4,5,6,7,8,9};
        //2.读取数组中的数据到流中,得到一个流对象
        Stream<Integer> stream = Arrays.stream(array);
        //3.输出Stream
        System.out.println(stream);
    }
    
    //将数组作为数据源,读取数组中的数据到一个流中
    //集合中只能存引用数据类型,但是数组中不用
    public static void arrayDataSource2(){
        //1.实例化一个数组
        int[] array = new int[]{0,1,2,3,4,5,6,7,8,9};
        //2.读取数组中的数据到流中,得到一个流对象
        IntStream stream = Arrays.stream(array);
        //3.输出Stream
        System.out.println(stream);
    }

    三、最终操作

    将流中的数据整合到一起,可以存入一个集合,也可以直接对流中的数据进行遍历,数据统计...通过最终操作,需要掌握如何从流中提取出来我们想要的信息。

    注意事项:最终操作,在执行结束之后,会关闭这个流,流中的所有数据都会被销毁,如果使用一个已经关闭了的流,会出现异常。

    最终操作包括:collect、reduce、count、forEach、max&min、Matching、find、IntStream等。

    1. collect

    将流中的数据收集到一起,对这些数据进行一些处理。最常见的处理,就是将流中的数据存入一个集合。collect方法的参数,是一个collector接口,而且这个接口并不是一个函数式接口,实现这个接口,可以自定义收集的规则。但是,绝大部分情况下,不需要自定义。
    直接使用Collectors工具类提供的方法即可。

    public class FinalOperation {
        public static void main(String[] args) {
            collectUsage();
        }
    
        //最终操作:collect将流中的数据整合起来,最常见的处理是:读取流中的数据,整合到一个容器中,得到一个集合。
        public static void collectUsage(){
            //1.读取数据源
            Stream<Integer> dataSource = getDataSource();
            //2.流中的数据的聚合
            //List<Integer> list = dataSource.collect(Collectors.toList());
            //System.out.println(list);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
            //Set<Integer> set = dataSource.collect(Collectors.toSet());
            //System.out.println(set);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
            //Map<String, Integer> map = dataSource.collect(Collectors.toMap(i -> i.toString(), i -> i));//i.toString作为键 i作为值
            Map<String, Integer> map = dataSource.collect(Collectors.toMap(Object::toString, i -> i));//i.toString作为键 i作为值
            System.out.println(map);//{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9}
        }
    
        //数据源的获取,从一个容器中获取数据源中的数据(得到一个Stream对象)
        public static Stream<Integer> getDataSource(){
            //1.准备一个容器
            List<Integer> dataSource = new ArrayList<>();
            //2.向数据源中添加数据
            Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            //3.读取数据源中的数据,得到Stream对象
            return dataSource.stream();
        }
    }
    View Code

    2. reduce

    将流中的数据按照一定的规则聚合起来。将流的元素,逐一带入这个方法中,进行运算。最终的运算结果,得到的其实是一个Optional类型,需要使用get()获取到里面的数据

    public class FinalOperation {
        public static void main(String[] args) {
            reduceUsage();
        }
    
        public static void reduceUsage(){
            //1.读取数据源,得到流对象
            Stream<Integer> dataSource = getDataSource();
            //2.最终操作 (这里有两个参数,实现了从0到9的和的求值 即p1=0 p2=1 和的结果为1作为p1 再跟p2=2相加,以此类推)
            Integer num = dataSource.reduce((p1, p2) -> p1 + p2).get();
            //Integer num = dataSource.reduce(Integer::sum).get();
            //3.输出
            System.out.println(num);//45
        }
    
        //数据源的获取,从一个容器中获取数据源中的数据(得到一个Stream对象)
        public static Stream<Integer> getDataSource(){
            //1.准备一个容器
            List<Integer> dataSource = new ArrayList<>();
            //2.向数据源中添加数据
            Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            //3.读取数据源中的数据,得到Stream对象
            return dataSource.stream();
        }
    }
    View Code

    3. count

    统计流中的元素数量

    public class FinalOperation {
        public static void main(String[] args) {
            countUsage();
        }
    
        public static void countUsage(){
            //1.读取数据源,得到流对象
            Stream<Integer> dataSource = getDataSource();
            //2.最终操作 获取元素数量
            Long num = dataSource.count();
            //3.输出
            System.out.println(num);//10
        }
    
        //数据源的获取,从一个容器中获取数据源中的数据(得到一个Stream对象)
        public static Stream<Integer> getDataSource(){
            //1.准备一个容器
            List<Integer> dataSource = new ArrayList<>();
            //2.向数据源中添加数据
            Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            //3.读取数据源中的数据,得到Stream对象
            return dataSource.stream();
        }
    }
    View Code

    4. forEach

    迭代、遍历流中的数据

    public class FinalOperation {
        public static void main(String[] args) {
            forEachUsage();
        }
    
        public static void forEachUsage(){
            //1.读取数据源,得到流对象
            Stream<Integer> dataSource = getDataSource();
            //2.最终操作 遍历流中的数据 输出
            dataSource.forEach(System.out::print);//0123456789
        }
    
        //数据源的获取,从一个容器中获取数据源中的数据(得到一个Stream对象)
        public static Stream<Integer> getDataSource(){
            //1.准备一个容器
            List<Integer> dataSource = new ArrayList<>();
            //2.向数据源中添加数据
            Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            //3.读取数据源中的数据,得到Stream对象
            return dataSource.stream();
        }
    }
    View Code

    5. max&min

    获取流中的最大/最小元素

    public class FinalOperation {
        public static void main(String[] args) {
            maxAndMinUsage();
        }
    
        //按照执行的对象比较的规则去进行大小的比较,然后得出流中最大、最小的数据
        public static void maxAndMinUsage(){
            //1.读取数据源,得到流对象
            Stream<Integer> dataSource = getDataSource();
            //2.最终操作 获取流中的最大、最小值
            //Integer max = dataSource.max(Integer::compareTo).get();
            //System.out.println(max);//9
            Integer min = dataSource.min(Integer::compareTo).get();
            System.out.println(min);//0
        }
    
        //数据源的获取,从一个容器中获取数据源中的数据(得到一个Stream对象)
        public static Stream<Integer> getDataSource(){
            //1.准备一个容器
            List<Integer> dataSource = new ArrayList<>();
            //2.向数据源中添加数据
            Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            //3.读取数据源中的数据,得到Stream对象
            return dataSource.stream();
        }
    }
    View Code

    6. Matching

    allMatch:只有当流中所有的元素,都匹配指定的规则,才会返回true
    anyMatch:只要流中有任意的数据,满足指定的规则,都会返回true
    noneMatch:只有当流中所有的元素,都不满足指定的规则,才会返回true

    public static void main(String[] args) {
        matchingUsage();
    }
    
    public static void matchingUsage(){
        //1.读取数据源,获取Stream对象
        Stream<Integer> dataSource = getDataSource();
        //2.匹配的操作
        //boolean b = dataSource.allMatch(e -> e>0);
        //System.out.println(b);//false 因为不是集合中所有的元素都大于0 还有一个等于0
        //boolean b = dataSource.anyMatch(e -> e >= 9);
        //System.out.println(b);//true
        boolean b = dataSource.noneMatch(e -> e > 9);
        System.out.println(b);//true
    }
    
    //数据源的获取,从一个容器中获取数据源中的数据(得到一个Stream对象)
    public static Stream<Integer> getDataSource(){
        //1.准备一个容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向数据源中添加数据
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.读取数据源中的数据,得到Stream对象
        return dataSource.stream();
    }
    View Code

    7. find

    findFirst:从流中获取一个元素(是获取的开头元素)
    findAny:从流中获取一个元素(一般情况下,是获取的开头的元素)
    这两个方法,绝大部分情况下,是完全相同的,但是在多线程环境下,返回结果可能不一样

    public static void main(String[] args) {
        findUsage();
    }
    
    public static void findUsage(){
        //1.实例化一个集合
        ArrayList<Integer> dataSource = new ArrayList<>();
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //2.findFirst演示
        //Integer integer = dataSource.stream().findFirst().get();//串行流
        //Integer integer = dataSource.parallelStream().findFirst().get();//并行流
        //System.out.println(integer);//串行流或者是并行流结果都是0
        //3.findAny演示
        //Integer integer = dataSource.stream().findAny().get();//串行流
        Integer integer = dataSource.parallelStream().findAny().get();//并行流
        System.out.println(integer);//串行流是0、并行流结果为6  即不一定是0
    }
    View Code

    8. IntStream

    主要可以实现获取流中int类型数据的最大值、最小值、平均值、和、数量
    还可以获取到一个对流中数据的分析结果(即一次获取所有类型的值)

    public static void main(String[] args) {
        intStreamUsage();
    }
    
    public static void intStreamUsage(){
        //1.准备一个int数组作为数据源
        int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        //2.读取数据到流中,获取IntStream对象
        IntStream stream = Arrays.stream(array);
        //3.输出
        //System.out.println(stream.max().getAsInt());//获取最大值     9
        //System.out.println(stream.min().getAsInt());//获取最小值     0
        //System.out.println(stream.sum());//获取和      45
        //System.out.println(stream.count());//获取流中数据个数   10
        //System.out.println(stream.average().getAsDouble());//获取流中数据的平均值   4.5
        //4.获取到一个对流中数据的分析结果(即一次获取所有类型的值)
        IntSummaryStatistics intSummaryStatistics = stream.summaryStatistics();
        System.out.println("最大值:"+intSummaryStatistics.getMax()+" 最小值:"+intSummaryStatistics.getMin());//最大值:9 最小值:0
        System.out.println("平均值:"+intSummaryStatistics.getAverage()+" 和:"+intSummaryStatistics.getSum());//平均值:4.5 和:45
        System.out.println("数量:"+intSummaryStatistics.getCount());//数量:10
    }
    View Code

    四、中间操作

    将数据从数据源中读取到流中,就是对流中的数据进行各种各样的操作、处理。中间操作可以连续操作,每一个操作的返回值都是一个Stream对象,可以继续进行其他的操作,直到最终操作。

    中间操作主要分为:filter、distinct、sorted、limit&skip、map&flatMap、Collections工具类

    1. filter

    条件过滤,仅保留流中满足指定条件的数据,其他不满足的数据都会被删除。

    //学生类:存储于集合中的数据类型
    private static class Student{
        private String name;
        private int age;
        private int score;
    
        public Student(String name, int age, int score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
        //这里省略getter、setter、toString方法
    }
    
    public static void main(String[] args) {
        filterUsage();
    }
    
    public static void filterUsage(){
        //1. 获取数据源
        Stream<Student> dataSource = getDataSource();
        //2. 过滤掉集合中成绩不合格的学生信息
        dataSource.filter(s -> s.getScore()>=60).forEach(System.out::println);
        //Student{name='xiaoming', age=18, score=100}
        //Student{name='xiaoming', age=19, score=90}
        //Student{name='xiaoming', age=20, score=80}
        //Student{name='xiaoming', age=21, score=70}
        //Student{name='xiaoming', age=22, score=60}
    }
    
    //读取数据源,将集合中存储的数据,读取到数据源中
    public static Stream<Student> getDataSource(){
        //1.实例化一个集合,存Student对象
        ArrayList<Student> arrayList = new ArrayList<>();
        //2.添加若干数据
        Collections.addAll(arrayList,
                           new Student("xiaoming",18,100),
                           new Student("xiaoming",19,90),
                           new Student("xiaoming",20,80),
                           new Student("xiaoming",21,70),
                           new Student("xiaoming",22,60),
                           new Student("xiaoming",23,50),
                           new Student("xiaoming",24,40)
                          );
        //3.读取数据源,得到Stream对象
        return arrayList.stream();
    }
    View Code

    2. distinct

    去除集合中重复的元素,这个方法没有参数,去重的规则与HashSet相同。
     (1)比较两个对象的hashcode
     (2)使用equals再来对比一下
    这里要注意:实体类中需要重写hashcode和equals方法,否则去重可能不会生效

    //学生类:存储于集合中的数据类型
    private static class Student{
        private String name;
        private int age;
        private int score;
    
        public Student(String name, int age, int score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
        //这里省略getter、setter、toString、hashcode、equals方法
    }
    
    public static void main(String[] args) {
        distinctUsage();
    }
    
    
    public static void distinctUsage(){
        //1. 获取数据源
        Stream<Student> dataSource = getDataSource();
        //2. 去重 要注意实体类Student中需要重写equals和hashCode方法,否则去重不会生效
        dataSource.distinct().forEach(System.out::println);
        //Student{name='xiaoming1', age=18, score=100}
        //Student{name='xiaoming2', age=20, score=80}
        //Student{name='xiaoming3', age=21, score=70}
        //Student{name='xiaoming4', age=22, score=60}
        //Student{name='xiaoming5', age=23, score=50}
        //Student{name='xiaoming6', age=24, score=40}
    
    }
    
    //读取数据源,将集合中存储的数据,读取到数据源中
    public static Stream<Student> getDataSource(){
        //1.实例化一个集合,存Student对象
        ArrayList<Student> arrayList = new ArrayList<>();
        //2.添加若干数据
        Collections.addAll(arrayList,
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming2",20,80),
                           new Student("xiaoming3",21,70),
                           new Student("xiaoming4",22,60),
                           new Student("xiaoming5",23,50),
                           new Student("xiaoming6",24,40)
                          );
        //3.读取数据源,得到Stream对象
        return arrayList.stream();
    }
    View Code

    3. sorted

    对流中的数据进行排序
     (1)无参:sorted():将流中的数据,按照其对应的类实现的Comparable接口提供的比较规则进行排序
     (2)有参:sorted(Comparator<T> comparator):将流中的数据,按照参数接口提供的比较规则进行排序

    private static class Student implements Comparable<Student>{
        private String name;
        private int age;
        private int score;
    
        public Student(String name, int age, int score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
    
        @Override
        public int compareTo(Student o) {
            return score-o.score;
        }
        //这里省略getter、setter、toString、hashcode、equals方法
    }
    
    public static void main(String[] args) {
        sortedUsage();
    }
    
    
    public static void sortedUsage(){
        //1. 获取数据源
        Stream<Student> dataSource = getDataSource();
        //2. 将流中的数据进行排序 (注意实体类要注意实现Comparable接口并重写compareTo方法,否则会报错)
        //dataSource.sorted().forEach(System.out::println);
        //Student{name='xiaoming6', age=24, score=40}
        //Student{name='xiaoming5', age=23, score=50}
        //Student{name='xiaoming4', age=22, score=60}
        //Student{name='xiaoming3', age=21, score=70}
        //Student{name='xiaoming2', age=20, score=80}
        //Student{name='xiaoming1', age=18, score=100}
        //Student{name='xiaoming1', age=18, score=100}
        //3. 对流中的数据按照自定义的规则进行排序 (按照年龄升序排列)
        dataSource.sorted((s1,s2)->s1.getAge()-s2.getAge()).forEach(System.out::println);
        //Student{name='xiaoming1', age=18, score=100}
        //Student{name='xiaoming1', age=18, score=100}
        //Student{name='xiaoming2', age=20, score=80}
        //Student{name='xiaoming3', age=21, score=70}
        //Student{name='xiaoming4', age=22, score=60}
        //Student{name='xiaoming5', age=23, score=50}
        //Student{name='xiaoming6', age=24, score=40}
    }
    
    //读取数据源,将集合中存储的数据,读取到数据源中
    public static Stream<Student> getDataSource(){
        //1.实例化一个集合,存Student对象
        ArrayList<Student> arrayList = new ArrayList<>();
        //2.添加若干数据
        Collections.addAll(arrayList,
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming2",20,80),
                           new Student("xiaoming3",21,70),
                           new Student("xiaoming4",22,60),
                           new Student("xiaoming5",23,50),
                           new Student("xiaoming6",24,40)
                          );
        //3.读取数据源,得到Stream对象
        return arrayList.stream();
    }
    View Code

    4. limit&skip

    limit:限制,截取流中指定数量的元素   skip:跳过流中的指定数量的元素 经常放在一起用

    //实体类省略,参考上面即可
    
    public static void main(String[] args) {
         limitAndSkipUsage();
     }
    
    
    public static void limitAndSkipUsage(){
        //1. 获取数据源
        Stream<Student> dataSource = getDataSource();
        //2. 获取成绩的前5名
        //        dataSource.distinct()
        //                .sorted((s1,s2)->s2.getScore()-s1.getScore())
        //                .limit(5)
        //                .forEach(System.out::println);
        //3. 获取成绩为3-5名的
        dataSource.distinct()
            .sorted((s1,s2)->s2.getScore()-s1.getScore())
            .limit(5)
            .skip(2)
            .forEach(System.out::println);
    }
    
    //读取数据源,将集合中存储的数据,读取到数据源中
    public static Stream<Student> getDataSource(){
        //1.实例化一个集合,存Student对象
        ArrayList<Student> arrayList = new ArrayList<>();
        //2.添加若干数据
        Collections.addAll(arrayList,
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming2",20,80),
                           new Student("xiaoming3",21,70),
                           new Student("xiaoming4",22,60),
                           new Student("xiaoming5",23,50),
                           new Student("xiaoming6",24,40)
                          );
        //3.读取数据源,得到Stream对象
        return arrayList.stream();
    }
    View Code

    5. map&flatMap

    对流中的数据进行映射,用新的数据替换旧的数据

    map最主要,就是来做元素的替换,其实map是一个元素的映射(将流中每一个元素替换成指定的元素)

    flatMap也是元素的映射,flatMap是扁平化映射

    扁平化映射:一般用在map映射完成后,流中的数据是一个容器,而我们需要对容器中的数据进行处理 此时使用扁平化映射,可以将流中的容器中的数据,直接读取到流中

    案例1:

    public static void main(String[] args) {
        mapUsage();
    }
    
    
    public static void mapUsage(){
        //1. 获取数据源
        Stream<Student> dataSource = getDataSource();
        //2. 实际需求:获取所有学生的名字
        //dataSource.map(Student::getName).forEach(System.out::println);
        //dataSource.map(s->s.getName()).forEach(System.out::println);
        //3. 实际需求:获取所有学生的成绩 注意:泛型中不能是基本数据类型,只能是包装类 即下面的返回值应该为Stream<Integer>
        //dataSource.map(Student::getScore).forEach(System.out::println);
        //4. 实际需求:获取所有学生的成绩
        IntSummaryStatistics intSummaryStatistics = dataSource.mapToInt(Student::getScore).summaryStatistics();
        System.out.println(intSummaryStatistics.getMax());
    }
    
    //读取数据源,将集合中存储的数据,读取到数据源中
    public static Stream<Student> getDataSource(){
        //1.实例化一个集合,存Student对象
        ArrayList<Student> arrayList = new ArrayList<>();
        //2.添加若干数据
        Collections.addAll(arrayList,
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming1",18,100),
                           new Student("xiaoming2",20,80),
                           new Student("xiaoming3",21,70),
                           new Student("xiaoming4",22,60),
                           new Student("xiaoming5",23,50),
                           new Student("xiaoming6",24,40)
                          );
        //3.读取数据源,得到Stream对象
        return arrayList.stream();
    }
    View Code

    案例2:

    public static void main(String[] args) {
        mapUsage();
    }
    
    public static void mapUsage(){
        //1.实例化一个字符串数组
        String[] array = {"hello","world"};
        //2.将字符串数组中的数据读取到流中
        Stream<String> stream = Arrays.stream(array);
        //3.需求:统计字符串数组中所有出现的字符
        //stream.map(String::toCharArray).forEach(e->System.out.println(Arrays.toString(e)));
        //结果为 [h, e, l, l, o]  [w, o, r, l, d] 两个数组 不符合我们的要求
        stream.map(s->s.split(""))
            .flatMap(Arrays::stream)
            .distinct()
            .forEach(System.out::println);
        //结果为h e l o w r d
    }
    View Code

    6. Collections工具类

    Collectors是一个工具类,里面封装了很多方法,可以很方便的获取到一个Collector接口的实现类对象,从而可以使用collect()方法,对流中的数据,进行各种各样的处理、整合。
    常用方法:
     Collectors.toList()  将流中的数据,聚合到一个List集合中
     Collectors.toSet()  将流中的数据,聚合到一个Set集合中
     Collectors.toMap()  将流中的数据,聚合到一个Map集合中
     maxBy()     按照指定的规则,找到流中最大的元素,等同于max
     minBy()     按照指定的规则,找到流中最小的元素,等同于min
     joining()     将流中的数据拼接成一个字符串,注意:只能操作流中是String的数据
     summingInt()    将流中的数据,映射成int类型的数据,并求和
     averagingInt()   将流中的数据,映射成int类型的数据,并求平均值
     summarizingInt()   将流中的数据,映射成int类型的数据,并获取描述信息

    public static void main(String[] args) {
        //1. 准备一个字符串数组,作为数据源
        String[] dataSource = {"nihao","wo","shi","xxx"};
        //2. 读取数据源中的数据
        Stream<String> stream = Arrays.stream(dataSource);
        //3. joining方法,只适用于 Stream<String> 这种流
        //String collect = stream.collect(Collectors.joining());//拼接
        //System.out.println(collect);//nihaowoshixxx
        //String collect = stream.collect(Collectors.joining(","));//拼接 按照逗号分隔
        //System.out.println(collect);//nihao,wo,shi,xxx
        //tring collect = stream.collect(Collectors.joining(",","[","]"));//拼接 带前缀、后缀
        //System.out.println(collect);//[nihao,wo,shi,xxx]
    
        //4. summingInt
        Integer collect = stream.collect(Collectors.summingInt(String::length));
        System.out.println(collect);//13
    }
    View Code

    持续更新!!!

    注意:本篇文章大多数内容来自bilibili网站千锋教育,地址:https://www.bilibili.com/video/BV1fT4y177ui?p=6  本篇文章仅用于个人学习和总结,如有侵权,联系删除!

  • 相关阅读:
    接口测试(apipost、jmeter和python脚本)
    接口测试人员需要掌握的知识技能
    使用抓包工具fiddler和apipost进行接口测试
    接口工具使用对比(apipost、jmeter、postman、swagger等)
    如何获取变量token的值
    接口文档生成工具apipost
    (Win10 应用中心打不开) Microsoft store 无法联网
    判断当前系统是64位还是32位
    VS2017 远程调试方法
    基于COM组件接口ICMLuaUtil的BypassUAC
  • 原文地址:https://www.cnblogs.com/flyinghome/p/13656637.html
Copyright © 2020-2023  润新知