文章
问答
冒泡
Java之Stream常用方法总结

之前知道Java8新特性有Stream流的操作,它允许开发人员以声明性方式处理集合,其核心类库主要改进了对集合类的 API和新增Stream操作。Stream类中每一个方法都对应集合上的一种操作。将真正的函数式编程引入到Java中,能让代码更加简洁,极大地简化了集合的处理操作,提高了开发的效率和生产力。

首先我们要知道stream不是一种数据结构,在Stream中每一次操作都会产生新的流,它的内部不会像普通集合那样立刻获取到值,而是"惰性"取值,就是只有用户真正需要结果的时候才会执行,并且我们无需再去关注线程和锁,Stream内部都已经实现好了。

Stream流总的来说有两大类分别是:

中间操作:会返回一个流,通过这种方式可以将多个中间操作连接起来,形成一个调用链,从而转换为另外 一个流。除非调用链后存在一个终端操作,否则中间操作对流不会进行任何结果处理。

终端操作:会返回一个具体的结果,如boolean、list、integer等。

下面我就列举一些常用的Stream里面的内置方法,首先先创建一个实体类对象,如下图:

基于filter()实现过滤数据:

 //  基于filter()实现数据过滤
//    筛选出年龄小于20的学生对象
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, 19, "张三", "M"));
        studentList.add(new Student(1, 18, "李四", "M"));
        studentList.add(new Student(1, 21, "王五", "F"));
        studentList.add(new Student(1, 20, "赵六", "F"));
        //studentList.stream().filter(student -> student.getAge() < 20).forEach(p -> System.out.println(p));
        Stream<Student> studentStream = studentList.stream().filter(student -> student.getAge() < 20);
        studentStream.forEach(p -> System.out.println(p));

结果如下:

 

基于distinct()实现数据去重:

 List<Integer> integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);
        //基于distinct实现数据去重
        integers.stream().distinct().collect(Collectors.toList()).forEach(p -> System.out.println(p));
        //基于limit()实现数据截取
        integers.stream().limit(5).forEach(p -> System.out.println("基于limit()实现数据截取==>" + p));
        //先从集合中截取5个元素,然后取后3个
        integers.stream().limit(5).skip(2).forEach(p -> System.out.println("先从集合中截取5个元素,然后取后3个==>" + p));

结果如下:

 

在Stream API中有一个map()方法,它接收一个函数作为方法参数,这个函数会被应用到集合中每一个元素上,并将其隐射为一个新的元素。

 List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, 19, "张三", "M"));
        studentList.add(new Student(1, 18, "李四", "M"));
        studentList.add(new Student(1, 21, "王五", "F"));
        studentList.add(new Student(1, 20, "赵六", "F"));
studentList.stream().map(Student::getName).collect(Collectors.toList()).forEach(p -> System.out.println("获取所有学生的姓名,并形成一个新的集合====>" + p));

结果如下:

还可以使用map()方法将T类型转换成R类型,这种转换动作称为:映射

 //创建一个流,里面是字符串类型的整数
        Stream<String> stream1 = Stream.of("2", "32", "2", "33", "2");
        
        //把stream1流中的整数全部转成int类型
        Stream<Integer> stream2 = stream1.map((String s) -> {
            return Integer.parseInt(s);
        });

        //遍历
        stream2.forEach((i)-> System.out.println(i));

结果如下:

 

基于anyMatch()判断条件至少匹配一个元素:

  List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, 19, "张三", "M"));
        studentList.add(new Student(1, 18, "李四", "M"));
        studentList.add(new Student(1, 21, "王五", "F"));
        studentList.add(new Student(1, 20, "赵六", "F"));

 //基于anyMatch()判断条件至少匹配一个元素
        if (studentList.stream().anyMatch(student -> student.getAge() < 20)) {
            System.out.println("集合中有年龄小于20的学生");
        } else {
            System.out.println("集合中没有年龄小于20的学生");
        }

结果如下:

 

基于allMatch()方法判断条件是否匹配所有元素:

 //基于allMatch()判断条件是否匹配所有元素
        if (studentList.stream().allMatch(student -> student.getAge() < 20)) {
            System.out.println("集合中所有学生年龄小于20");
        } else {
            System.out.println("集合中有年龄大于20的学生");
        }

结果如下:

注意:allMatch()的工作原理与anyMatch()类似,但是anyMatch执行时,只要流中有一个元素符合条件就会返回true, 而allMatch会判断流中是否所有条件都符合条件,全部符合才会返回true。

 

基于reduce()进行累加求和:

//基于reduce()进行累积求和
        Integer reduce = integers.stream().reduce(0, (v1, v2) -> v1 + v2);
        System.out.println("基于reduce()进行累积求和:" + reduce);
        //优化代码,在reduce里的第一个参数声明为初始值,第二个参数接收一个lambda表达式,代表当前流中的两 个元素,它会反复相加每一个元素,直到流被归约
        //成一个终结果
        Integer reduceGood = integers.stream().reduce(0, Integer::sum);
        System.out.println("利用Lambda表达式基于reduce()进行累积求和:" + reduceGood);

结果如下:

 

通过使用收集器,可以让代码更加方便的进行简化与重用。其内部主要核心是通过Collectors完成更加复杂的计算 转换,从而获取到终结果。并且Collectors内部提供了非常多的常用静态方法,直接拿来就可以了。比方刚刚上面所说: toList。

 ArrayList<Student> students = new ArrayList<>();
        students.add(new Student(1, 19, "张三1", "M"));
        students.add(new Student(1, 18, "张三2", "M"));
        students.add(new Student(1, 21, "张三3", "F"));
        students.add(new Student(1, 20, "张三4", "F"));
        students.add(new Student(1, 20, "张三5", "F"));
        students.add(new Student(1, 20, "张三6", "F"));

 //通过counting()统计集合总数  方法一
        Long collect1 = students.stream().collect(Collectors.counting());
          System.out.println("通过counting()统计集合总数"+collect1);
          //结果 6

          //通过count()统计集合总数  方法二
          long count1 = students.stream().count();
          System.out.println("通过count()统计集合总数"+count1);
          //结果 6

          //通过maxBy求最大值
          Optional<Student> collect2 = students.stream().collect(Collectors.maxBy(Comparator.comparing(Student::getAge)));
          if(collect2.isPresent()){
              System.out.println(collect2);
          }
          //结果 Optional[Student{id=1, age=21, name='张三3', gender='F'}]

          //通过max求最大值
          Optional<Student> max = students.stream().max(Comparator.comparing(Student::getAge));
          if(max.isPresent()){
              System.out.println(max);
          }
          //结果  Optional[Student{id=1, age=21, name='张三3', gender='F'}]

          //通过minBy求最小值
          Optional<Student> collectMin = students.stream().collect(Collectors.minBy(Comparator.comparing(Student::getAge)));
          if(collectMin.isPresent()){
              System.out.println(collectMin);
          }
          //结果  Optional[Student{id=1, age=18, name='张三2', gender='M'}]

          //通过min求最小值
          Optional<Student> min = students.stream().min(Comparator.comparing(Student::getAge));
          if(min.isPresent()){
              System.out.println(min);
          }
          //结果  Optional[Student{id=1, age=18, name='张三2', gender='M'}]

          //通过summingInt()进行数据汇总
          Integer collect3 = students.stream().collect(Collectors.summingInt(Student::getAge));
          System.out.println(collect3);
          //结果 118

          //通过averagingInt()进行平均值获取
          Double collect4 = students.stream().collect(Collectors.averagingInt(Student::getAge));
          System.out.println(collect4);
          //结果 19.666666666666668

        //通过joining()进行数据拼接
        String collect5 = students.stream().map(Student::getName).collect(Collectors.joining());
        System.out.println(collect5);
        //结果 张三1张三2张三3张三4张三5张三6

 

那么我们如何利用Stream流将一个List集合转换成Map集合:Collectors里面提供了toMap()方法:

  User u1 = new User(1, "张三");
        User u2 = new User(2, "李四");
        User u3 = new User(3, "王五");
        User u4 = new User(3, "赵六");
List<User> list = new ArrayList<>();
        list.add(u1);
        list.add(u2);
        list.add(u3);
        list.add(u4);

        Map<Integer, User > collect = list.stream().collect(Collectors.toMap(User ::getId, Function.identity()));
        Map<Integer, User > collect1 = list.stream().collect(Collectors.toMap(User ::getId, Function.identity(), (a,b)->a));
         /**
        使用toMap()函数之后,返回的就是一个Map了,自然会需要key和value。
        toMap()的第一个参数就是用来生成key值的,第二个参数就是用来生成value值的。
        第三个参数用在key值冲突的情况下:如果新元素产生的key在Map中已经出现过了,第三个参数就会定义解决的办法。
         * 第一个参数:User:getId表示选择User的getId作为map的key值;
         *
         * 第二个参数:v->v表示选择将原来的对象作为Map的value值
         *
         * 第三个参数:(a,b)->a中,如果a与b的key值相同,选择a作为那个key所对应的value值。
         */
        Map<Integer, User> collect = list.stream().collect(Collectors.toMap(User::getId, v -> v, (v1, v2) -> v1));
        System.out.println(collect);
        Collection<User > values = list.stream().collect(Collectors.toMap(User ::getId, Function.identity(), (a, b) -> a)).values();
        long count = list.stream().collect(Collectors.toMap(User ::getId, Function.identity(), (a, b) -> a)).values().stream().count();
        System.out.println(collect1);
        System.out.println(collect2);
        System.out.println(values);
        System.out.println(count);

结果如下:

 

将Map集合转换成List集合:Collectors.toList()方法:

            Map<Integer, String> map = new HashMap<>();
            map.put(23, "张三");
            map.put(10, "李四");
            map.put(26, "王五");
            map.put(11, "赵六");
            System.out.println("--将map的value值转换成List集合--");
            List<String> valueList = map.values().stream().collect(Collectors.toList());
            valueList.forEach(n -> System.out.println("map的value值转换成List集合"+n));

            System.out.println("--将map的value值通过sorted方法转换成List集合--");
            List<String> sortedValueList = map.values().stream()
                    .sorted().collect(Collectors.toList());
            sortedValueList.forEach(n -> System.out.println("将map的value值通过sorted方法转换成List集合"+n));

            System.out.println("--将map的key值转换成List集合--");
            List<Integer> keyList = map.keySet().stream().collect(Collectors.toList());
            keyList.forEach(n -> System.out.println("将map的key值转换成List集合"+n));

            System.out.println("--将map的key值通过sorted方法转换成List集合--");
            List<Integer> sortedKeyList = map.keySet().stream()
                    .sorted().collect(Collectors.toList());
            sortedKeyList.forEach(n -> System.out.println("将map的key值转换成List集合"+n));

结果如下:


关于作者

Taurus
获得点赞
文章被阅读