1.功能

Stream流,用于操作集合或数组的数据

2.优势

Stream流大量结合Lambda表达式的语法风格来编程,提供更简单、强大的方式操作集合或数组中的数据,代码更简洁,可读性更好

3.示例

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

        // 找出姓张,但是3个字的名字,存入到一个新集合中去。
        List<String> list = new ArrayList<>();
        for (String name : names) {
            if (name.startsWith("张") && name.length() == 3) {
                list.add(name);
            }
        }
        System.out.println(list);

        // 开始使用Stream流来解决这个需求。
        List<String> streamList = names.stream()
                                       .filter(name -> name.startsWith("张") && name.length() == 3)
                                       .collect(Collectors.toList());
        System.out.println(streamList);
    }
}

4.使用步骤

Stream_System

(1)获取Stream流

Stream_数组_02

public class test {
    public static void main(String[] args) {
        // 1. 如何获取List集合的Stream流
        List<String> names = new ArrayList<>();
        Collections.addAll(names, "张三丰", "张无忌", "周芷若", "赵敏", "张强");
        Stream<String> stream = names.stream();

        // 2. 如何获取Set集合的Stream流
        Set<String> set = new HashSet<>();
        Collections.addAll(set, "刘德华", "张学友", "蜘蛛精", "马德", "倚西西");
        Stream<String> stream1 = set.stream();
        stream1.filter(s -> s.startsWith("张")).forEach(System.out::println);

        // 3. 如何获取Map集合的Stream流
        Map<String, Double> map = new HashMap<>();
        map.put("古力娜扎", 172.3);
        map.put("迪丽热巴", 168.3);
        map.put("李沁", 166.3);
        map.put("卡尔凡", 168.3);

        Set<String> keys = map.keySet();
        Stream<String> ks = keys.stream();

        Collection<Double> values = map.values();
        Stream<Double> vs = values.stream();

        Set<Map.Entry<String, Double>> entries = map.entrySet();// 注意:entrySet()返回的是Set集合,而非Stream流
        Stream<Map.Entry<String, Double>> kvs = entries.stream();
        kvs.filter(e -> e.getKey().contains("丽"))
           .forEach(e -> System.out.println(e.getKey() + "-->" + e.getValue()));

        // 4. 如何获取数组的Stream流
        String[] names2 = {"求求呆", "东方不败", "唐大山", "独孤求败"};
        Stream<String> stream2 = Arrays.stream(names2);
        stream2.forEach(System.out::println);
        //或者
        Stream<String> s2 = Stream.of(names2);
    }
}

(2)Stream流的中间方法

中间方法指的是调用完成后返回新的Stream流,可以继续使用(支持链式编程)。

Stream_System_03

public class test {
    public static void main(String[] args) {
        // 需求1:找出成绩大于等于60的成绩数据,并升序后,再输出。
        List<Double> scores = new ArrayList<>();
        Collections.addAll(scores, 88.5, 100.0, 60.0, 99.0, 9.5, 99.6, 25.0);
        scores.stream().filter(s -> s >= 60).sorted().forEach(s -> System.out.println(s));

        // 学生对象
        List<Student> students = new ArrayList<>();
        Student s1 = new Student("蜘蛛精", 26, 172.5);
        Student s2 = new Student("蜘蛛精", 26, 172.5);
        Student s3 = new Student("紫霞", 23, 167.6);
        Student s4 = new Student("白晶晶", 25, 169.0);
        Student s5 = new Student("牛魔王", 35, 183.3);
        Student s6 = new Student("牛大人", 34, 168.5);
        Collections.addAll(students, s1, s2, s3, s4, s5, s6);

        // 需求2:找出年龄大于等于23,且年龄小于等于30岁的学生,并按照年龄升序输出。
        students.stream()
            .filter(s -> s.getAge() >= 23 && s.getAge() <= 30)
            .sorted((o1, o2) -> o2.getAge() - o1.getAge())
            .forEach(s -> System.out.println(s));

        // 需求3:取出身高最高的前3名学生,并输出。
        students.stream()
            .sorted((o1, o2) -> Double.compare(o2.getHeight(), o1.getHeight()))
            .limit(3)
            .forEach(System.out::println);
        System.out.println("------------------------------------------------");

        // 需求4:取出身高最低的2名学生,并输出。
        students.stream()
            .sorted((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()))
            .skip(students.size() - 2)
            .forEach(System.out::println);

        // 需求5:找出身高超过168的学生叫什么名字,要求去除重复的名字,再输出。
        students.stream()
            .filter(s -> s.getHeight() > 168)
            .map(Student::getName)//对元素进行加工,只取出名字
            .distinct()
            .forEach(System.out::println);

        // distinct去重, 自定义类型的对象(希望内容一样就认为重复,在Student构造器重写hashCode, equals)
        students.stream()
            .filter(s -> s.getHeight() > 168)
            .distinct()
            .forEach(System.out::println);
        //concat合并两个流
        Stream<String> st1 = Stream.of("张三", "李四");
        Stream<String> st2 = Stream.of("张三", "李四2", "王五");
        Stream<String> allSt = Stream.concat(st1, st2);
        allSt.forEach(System.out::println);

    }
}

(3)终结方法

调用完成后,不返回新Stream流,无法继续使用流。

Stream_System_04

收集Stream流:把Stream流操作后的结果转回到集合或者数组中去返回

Stream_System_05

public class test {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        Student s1 = new Student("蜘蛛精", 26, 172.5);
        Student s2 = new Student("蜘蛛精", 26, 172.5);
        Student s3 = new Student("紫霞", 23, 167.6);
        Student s4 = new Student("白晶晶", 25, 169.0);
        Student s5 = new Student("牛魔王", 35, 183.3);
        Student s6 = new Student("牛夫人", 34, 168.5);
        Collections.addAll(students, s1, s2, s3, s4, s5, s6);

        // 需求1:请找出身高超过168的学生有几人。
        long size = students.stream().filter(s -> s.getHeight() > 168).count();
        System.out.println(size);

        // 需求2:请找出身高最高的学生对象,并输出。
        Student tallest = students.stream()
            .max((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()))
            .get();
        System.out.println(tallest);

        // 需求3:请找出身高最低的学生对象,并输出。
        Student shortest = students.stream()
            .min((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()))
            .get();
        System.out.println(shortest);
        // 需求4:请找出身高超过170的学生对象,并放到一个新集合中去返回。
        List<Student> students1 = students.stream()
            .filter(a -> a.getHeight() > 170)//流只能收集一次,所以需要重新创建流
            .collect(Collectors.toList());
        System.out.println(students1);
        
        Set<Student> students2 = students.stream()
            .filter(a -> a.getHeight() > 170)//流只能收集一次,所以需要重新创建流
            .collect(Collectors.toSet());
        System.out.println(students2);
        
        // 需求5:请找出身高超过170的学生对象,并把学生对象的名字和身高,存入到一个Map集合去返回。
        Map<String, Double> map = students.stream()
            .filter(a -> a.getHeight() > 170)
            .distinct()
            .collect(Collectors.toMap(
                Student::getName, 
                Student::getHeight
            ));
        System.out.println(map);
        
        // 将流转换为数组
        Student[] arr = students.stream()
            .filter(a -> a.getHeight() > 170)
            .toArray(len -> new Student[len]);
        System.out.println(Arrays.toString(arr));


    }
}