一.学习Stream流之前,我们先看一下下面这个问题

任务要求:有如下一个ArrayList集合,只要名字为3个字的成员姓名,筛选之后且只要前三个人

 List<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("孙悟空");
        one.add("猪八戒");
        one.add("古力娜扎");
        one.add("洪七公");
        one.add("唐三藏");

1.使用传统的实现方法如下:

//    将集合进行筛选,只要名字为3个字的成员姓名,并且只要前三个人
        List<String> one1 = new ArrayList<>();
        for (String name : one) {
            if (name.length() == 3){
                one1.add(name);
            }
        }
            List<String> one2 = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                one2.add(one1.get(i));
            }
        System.out.println(one2);

2.使用Stream实现如下:

        Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);
            oneStream.forEach((p) ->{
                System.out.println(p);
            });
        System.out.println(oneStream);

二.什么是Stream流?

(1)Stream流是JDK1.8之后出现的,Stream流其实是一个集合元素的函数模型,他并不是集合,也不是数据结构,其本身并不会存储任何元素(或地址值)
(2)Stream流属于管道流,只能被使用一次,当一个Stream流使用过后,就不能再调用方法了

//        创建一个stream流
        Stream<String> stream = Stream.of("马云", "王健林", "马化腾");
//        对Stream流中的元素进行过滤,只要姓马的人
        Stream<String> stream1 = stream.filter((String name) -> {
            return name.startsWith("马");
        });
//        遍历Stream流     
        stream1.forEach(name -> System.out.println(name));
//Stream是管道流,下面这个会报IllegalStateException: stream has already been operated upon or closed异常
    	stream.forEach(name -> System.out.println(name));

三.Stream流的获取

1.获取Stream流
(1)所有的Collections集合都可以通过stream或parallelStream方法获取流;
default Stream stream()
default Stream parallelStream()

ArrayList<Object> list = new ArrayList<>();
Stream<Object> stream = list.parallelStream();

(2) Stream接口的静态方法of可以获取数组对应的流
static Stream of(T values)
注:参数是一个可变参数,那么我们就可以传递一个数组.

//        把集合转换为Stream流
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();
//        Map集合可以间接转换为Stream
        Map<String,String> map = new HashMap<>();
//        获取键,存储到一个set集合中
        Set<String> keySet = map.keySet();
        Stream<String> stream2 = keySet.stream();
//        获取值,存储到一个Collection集合中
        Collection<String> values = map.values();
        Stream<String> stream3 = values.stream();
//        获取键值对(键与值的映射关系  entrySet)
        Set<Map.Entry<String, String>> entries = map.entrySet();
        Stream<Map.Entry<String, String>> stream4 = entries.stream();
//        把数组转换为Stream流
        Stream<Integer> stream5 = Stream.of(1, 2, 7, 9);
//        可变参数可以传递数组
        Integer[] arr = {2,3,4,6};
        Stream<Integer> stream6 = Stream.of(arr);

四.Stream流的常用方法

在这里插入图片描述

1.void forEach(Consumer<? super T> action)
该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理
Consumer接口是一个消费型的函数式接口,可以传递Lambda表达式,消费数据
简言之:foreach方法就是用来遍历流中的数据,并且是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法

//        获取一个Stream流
        Stream<String> stream = Stream.of("亚瑟", "李白", "鲁班");
//        使用Stream流中的方法forEach对Stream流中的数据进行遍历
        stream.forEach((String name) ->{
                    System.out.println(name);}

2.Stream filter(Predicate<? super T> predicate)
filter方法的参数Predicate是一个函数式接口,可以传递Lambda表达式,对数据进行过滤

//        创建一个stream流
        Stream<String> stream = Stream.of("马云", "王健林", "马化腾");
//        对Stream流中的元素进行过滤,只要姓马的人
        Stream<String> stream1 = stream.filter((String name) -> {
            return name.startsWith("马");
        });
//        遍历Stream流
        stream1.forEach(name -> System.out.println(name));

3. Stream map(Function<? super T, ? extends R> mapper);
map方法可以将流中的元素映射到另一个流中,该接口需要一个Function函数式(函数型接口)接口参数,可以将流中的T类型转换
为另一种R类型的流。

// 获取一个String类型的Stream流
        Stream<String> stream = Stream.of("1", "2", "4", "6");
// 使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
        Stream<Integer> stream1 = stream.map((String s) -> {
            return Integer.parseInt(s);
        });
//  遍历Stream流
        stream1.forEach(i -> System.out.println(i));

补充:
(1)map:接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其
映射成一个新的元素
(2)flatMap:接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流

4.Stream limit(long maxSize);
用于截取流中的元素,参数是一个long类型,如果集合当前长度大于参数进行截取,否则不进行操作
limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法

  Stream<String> stream = Stream.of("胡歌", "彭于晏", "马天宇","刘德华");
        Stream<String> stream1 = stream.limit(3);
        stream1.forEach(name -> System.out.println(name));

5.Stream skip(long n);
用于跳过前几个元素,可以使用skip方法获取一个截取之后的新流;
如果流的长度大于n,则跳过前n个元素;否则将会得到一个长度为0的空流

 Stream<Integer> stream = Stream.of(1, 2, 4, 9);
        Stream<Integer> stream1 = stream.skip(2);
        stream1.forEach(name -> System.out.println(name));

6.public static Stream concat(Stream<? extends T> a, Stream<? extends T> b)
用于把流组合到一起

  Stream<String> stream1 = Stream.of("周星驰", "李小龙", "成龙");
        Stream<String> stream2 = Stream.of("胡歌", "彭于晏");
        Stream<String> stream = Stream.concat(stream1, stream2);
        stream.forEach(name -> System.out.println(name));

7.排序
(1)sorted()——自然排序(Comparable,按照字典排)
(2)sorted(Comparator com)——定制排序(Comparator)
8.终止操作
(1)allMatch——检查是否匹配所有元素
(2)anyMatch——检查是否至少匹配一个元素
(3)noneMatch——检查是否没有匹配所有元素
(4)findFirst——返回第一个元素
(5)findAny——返回当前流中的任意元素
(6)count——返回流中元素的总个数
(7)max——返回流中最大值
(8)min——返回流中最小值
9.规约
T reduce(T identity, BinaryOperator<T> accumulator):可以将流中元素反复结合起来,得到一个值,返回T
Optional<T> reduce(BinaryOperator<T> accumulator):可以将流中元素反复结合起来,得到一个值,返回Optional<T>


        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);//得到总和
//        先把0作为x,y作为1,x+y=1;再把结果1作为x
        System.out.println(sum);

10.收集
collect(Collcetor c) 方法,收集流中的数据到【集合】或者【数组】中去。
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)。但是Collectors实用类提供了
很多静态方法,可以方便的创建常见收集器实例

//1.收集数据到list集合中
stream.collect(Collectors.toList())
//2.收集数据到set集合中
stream.collect(Collectors.toSet())

版权声明:本文为y516369原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/y516369/article/details/125712468