Stream流

1 Stream流的概述

1.1 Stream流的目的

目的:用于简化集合和数组操作的API

▶【案例】体现Stream流的作用

需求:按照下面的要求完成集合的创建和遍历

①创建一个集合,存储多个字符串元素

②把集合中所有以"张"开头的元素存储到一个新的集合

③把"张"开头的集合中的长度为3的元素存储到一个新的集合

④遍历上一步得到的集合中的元素输出。

public class StreamTest {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<>();
        Collections.addAll(names,"张三丰","张无忌","周芷若","赵敏","张强");
        System.out.println(names);

        //1.从集合中找出姓张的放在新集合
        ArrayList<String> zhangList = new ArrayList<>();
        for (String name : names) {
            if (name.startsWith("张")){
                zhangList.add(name);
            }
        }
        System.out.println(zhangList);

        //2.找名称长度是3的名字
        ArrayList<String> zhangThreeList = new ArrayList<>();
        for (String name : zhangList) {
            if (name.length()==3){
                zhangThreeList.add(name);
            }
        }
        System.out.println(zhangThreeList);

        System.out.println("-------------------------------------------");

        // 【使用Stream实现】
        names.stream()
                .filter(s -> s.startsWith("张"))
                .filter(s -> s.length()==3)
                .forEach(s -> System.out.println(s));

    }
}

运行结果:

[张三丰, 张无忌, 周芷若, 赵敏, 张强]
[张三丰, 张无忌, 张强]
[张三丰, 张无忌]
-------------------------------------------
张三丰
张无忌

1.2 Stream流思想

① 先得到集合或者数组的Stream流(就是一根传送带)。

② 把元素放上去。

③ 然后就用这个Stream流简化的API来方便的操作元素。


 

2 Stream流的获取

2.1 Stream流的三类方法

获取Stream流  —— 创建一条流水线,并把数据放到流水线上准备进行操作

中间方法 —— 流水线上的操作,一次操作完毕后,还可以继续进行其它操作

终结方法 —— 一个Stream流只能由一个终结方法,是流水线上的最后一个操作

2.2 集合、数组获取流

● Stream操作集合/数组的第一步就是先得到Stream流,然后才能使用流的功能。

 ① 集合获取Stream流

   可以使用Collection接口中的默认方法 stream​() 来生成流

名称 说明
default Stream<E> stream() 获取当前集合对象的stream流

② 数组获取Stream流

名称 说明
public static <T> Stream<T> stream(T[] array) 获取当前数组的Stream流
public static<T> Stream<T> of(T... value) 获取当前数组/可变数据的stream流

【案例】

public class StreamDemo02 {
    public static void main(String[] args) {
        /*-----------------Collection集合获取流-----------------*/
        ArrayList<String> list = new ArrayList<>();
        Stream<String> s = list.stream();

        /*-----------------Map集合获取流-----------------*/
        HashMap<String, Integer> maps = new HashMap<>();
        //键流
        Stream<String> keyStream = maps.keySet().stream();
        //值流
        Stream<Integer> valueStream = maps.values().stream();
        //键值对流(拿整体)
        Stream<Map.Entry<String, Integer>> keyAndValueStream = maps.entrySet().stream();

        /*-----------------数组集合获取流-----------------*/
        String[] names = {"赵敏","小昭","灭绝","周芷若"};
        Stream<String> nameStream = Arrays.stream(names);  //方式一
        Stream<String> nameStream2 = Stream.of(names);     // 方式二

    }
}

 


 

3 Stream流的常用API

3.1 常用API(中间操作方法)

名称 说明
Stream<T> filter(Predicate<? super T> predicate) 用于对流中的数据进行过滤
Stream<T> limit​(long maxSize) 获取前几个元素
Stream<T> skip​(long n) 跳过前几个元素
Stream<T> distinct​() 去除流中重复的元素。依赖(hashCode和equals方法)
static <T> Stream<T> concat​(Stream a, Stream b) 合并a和b两个流为一个流

注意:

● 中间方法也称为非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程。

● 在Stream流中无法直接修改集合、数组中的数据。

3.2 常见终结操作方法

名称 说明
void forEach​(Consumer action) 对此流的每个元素执行遍历操作
long count​() 返回此流中的元素数

注意:

● 终结操作方法,调用完成后流就无法继续使用了,原因是不会返回Stream了。

【案例】

/**
     目标:Stream流的常用API
         forEach : 逐一处理(遍历)
         count:统计个数
            -- long count();
         filter : 过滤元素
            -- Stream<T> filter(Predicate<? super T> predicate)
         limit : 取前几个元素
         skip : 跳过前几个
         map : 加工方法
         concat : 合并流。
 */
public class StreamDemo03 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.add("张三丰");

        // Stream<T> filter(Predicate<? super T> predicate)
        list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));

        long size = list.stream().filter(s -> s.length() == 3).count();
        System.out.println(size);

       // list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(s -> System.out.println(s));
        list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(System.out::println);

        list.stream().filter(s -> s.startsWith("张")).skip(2).forEach(System.out::println);

        // map加工方法: 第一个参数原材料  -> 第二个参数是加工后的结果。
        // 给集合元素的前面都加上一个:黑马的:
        list.stream().map(s -> "黑马的:" + s).forEach(a -> System.out.println(a));

        // 需求:把所有的名称 都加工成一个学生对象。
         list.stream().map(s -> new Student(s)).forEach(s -> System.out.println(s));
//        list.stream().map(Student::new).forEach(System.out::println); // 构造器引用  方法引用

        // 合并流。
        Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
        Stream<String> s2 = Stream.of("java1", "java2");
        // public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
        Stream<String> s3 = Stream.concat(s1 , s2);
        s3.distinct().forEach(s -> System.out.println(s));
    }
}

运行结果:

张无忌
张强
张三丰
张三丰
4
张无忌
张强
张三丰
张三丰
黑马的:张无忌
黑马的:周芷若
黑马的:赵敏
黑马的:张强
黑马的:张三丰
黑马的:张三丰
Student{name='张无忌'}
Student{name='周芷若'}
Student{name='赵敏'}
Student{name='张强'}
Student{name='张三丰'}
Student{name='张三丰'}
张无忌
张强
张三丰
java1
java2

 


 

4 收集Stream流

4.1 收集操作

收集Stream流的含义:就是把Stream流操作后的结果数据转回到集合或者数组中去。

● Stream流:方便操作集合/数组的手段

● 集合/数组:才是开发中的目的

4.2 收集方法

名称 说明
R collect(Collector collector) 开始收集Stream流,指定收集器

Collectors工具类提供了具体的收集方式

名称 说明
public static <T> Collector toList​() 把元素收集到List集合中
public static <T> Collector toSet​() 把元素收集到Set集合中
public static  Collector toMap​(Function keyMapper , Function valueMapper) 把元素收集到Map集合中

【案例】

/**
 目标:收集Stream流的数据到 集合或者数组中去。
 */
public class StreamDemo05 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.add("张三丰");

        Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
        List<String> zhangList = s1.collect(Collectors.toList()); // 可变集合
        zhangList.add("java1");
        System.out.println(zhangList);

//       List<String> list1 = s1.toList(); // 得到不可变集合
//       list1.add("java");
//       System.out.println(list1);

        // 注意注意注意:“流只能使用一次”
        Stream<String> s2 = list.stream().filter(s -> s.startsWith("张"));
        Set<String> zhangSet = s2.collect(Collectors.toSet());
        System.out.println(zhangSet);

        Stream<String> s3 = list.stream().filter(s -> s.startsWith("张"));
//         Object[] arrs = s3.toArray();
        String[] arrs = s3.toArray(String[]::new); // 可以不管,拓展一下思维!!
        System.out.println("Arrays数组内容:" + Arrays.toString(arrs));

    }
}

运行结果:

[张无忌, 张强, 张三丰, 张三丰, java1]
[张强, 张三丰, 张无忌]
Arrays数组内容:[张无忌, 张强, 张三丰, 张三丰]

注意:流只能用一次

 

posted @ 2022-04-27 20:46  白森  阅读(62)  评论(0编辑  收藏  举报