• Java8 Stream流


    Stream流

    Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

    Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

    Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

    这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

    元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

    image-20220808103626965

    1 起始操作

    在 Java 8 中, 集合接口有两个方法来生成流:

    • stream() − 为集合创建串行流。
    • parallelStream() − 为集合创建并行流。

    生成流

    // 为集合创建串行流
    Stream<String> stream = list.stream();
    
    // 为集合创建并行流
    Stream<String> stream = list.parallelStream();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2 中间操作

    过滤器

    public class Demo01 {
        public static void main(String[] args) {
            //创建一个集合,存储多个字符串元素。
            List<String> list = new ArrayList<>();
    
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
            /*
                filter()方法是中间操作,中间操作都用lambda表达式。
             */
    
            //需求1:把list集合中以“张”开头的元素在控制台输出。
            System.out.println("======需求1=====");
            list.stream().filter(x -> x.startsWith("张")).forEach(System.out::println);
    
            //需求2:把list集合中长度为3的元素在控制台输出。
            System.out.println("======需求2=====");
            list.stream().filter(x -> x.length() == 3).forEach(System.out::println);
    
            //需求3:把list集合中以“张”开头的,长度为3的元素在控制台输出。
            System.out.println("======需求3=====");
            //在一个过滤器中要满足两个条件。
            list.stream().filter(x -> x.startsWith("张") && x.length() == 3).forEach(System.out::println);
            System.out.println("-----");
            //用两个过滤器,先过滤出以“张”开头的元素,再过滤出长度为3的元素。
            list.stream().filter(x -> x.startsWith("张")).filter(x -> x.length() == 3).forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    理解stream流的时候,可以顺便复习复习lambda表达式。

    // 1. 不需要参数,返回值为 5  
    () -> 5  
      
    // 2. 接收一个参数(数字类型),返回其2倍的值  
    x -> 2 * x  
      
    // 3. 接受2个参数(数字),并返回他们的差值  
    (x, y) -> x – y  
      
    // 4. 接收2个int型整数,返回他们的和  
    (int x, int y) -> x + y  
      
    // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
    (String s) -> System.out.print(s)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    限制、跳过

    /*
        中间操作
            限制:limit()
            跳过:skip()
     */
    public class Demo02 {
        public static void main(String[] args) {
            //创建一个集合,存储多个字符串元素。
            List<String> list = new ArrayList<>();
    
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
    
            //需求1:取前3个数据在控制台输出。
            System.out.println("======需求1======");
            list.stream().limit(3).forEach(System.out::println);
            //需求2:跳过3个元素,把剩下的元素在控制台输出。
            System.out.println("=====需求2=======");
            list.stream().skip(3).forEach(System.out::println);
            //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出。
            System.out.println("=====需求3======");
            //先用一个skip(2)跳过前两个元素,在剩下的元素中用limit(2)取前两个元素并输出。
            list.stream().skip(2).limit(2).forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    合并流、去重

    /*
        中间操作
            合并流:concat()------这是一个静态方法。Stream.concat()
            去重:distinct()
    
     */
    public class Demo03 {
        public static void main(String[] args) {
            //创建一个集合,存储多个字符串元素。
            List<String> list = new ArrayList<>();
    
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
    
            //需求1:取前4个数据组成一个流。
            Stream<String> stream1 = list.stream().limit(4);
            //需求2:跳过2个数据组成一个流。
            Stream<String> stream2 = list.stream().skip(2);
            //需求3:合并需求1和需求2得到的流,并把结果在控制台输出。
            //合并流的方法concat()是一个静态方法。
            Stream.concat(stream1, stream2).forEach(System.out::println);
    
            //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复。
            Stream.concat(stream1, stream2).distinct().forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    排序

    /*
        中间操作
            自然排序:sorted()
            用比较器比较排序:sorted(Comparator comparator)
     */
    public class Demo04 {
        public static void main(String[] args) {
            //创建一个集合,存储多个字符串元素。
            List<String> list = new ArrayList<>();
            list.add("linqingxia");
            list.add("zhangmanyu");
            list.add("wangzuxian");
            list.add("liuyan");
            list.add("zhangming");
            list.add("zhangwuji");
    
            //需求1:按照字母顺序把数据在控制台输出。
            System.out.println("====需求1====");
            list.stream().sorted().forEach(System.out::println);
            //需求2:按照字符串长度把数据在控制台输出。
            System.out.println("====需求2====");
            //前面-后面:从小到大    后面-前面:从大到小
            list.stream().sorted((s1, s2) -> s1.length() - s2.length()).forEach(System.out::println);
            //需求3:先按照长度,再按照字母顺序排序。
            System.out.println("====需求3====");
            list.stream().sorted((s1, s2) -> {
                int sort1 = s1.length() - s2.length();
                int sort2 = sort1 == 0 ? s1.compareTo(s2) : sort1;
                return sort2;
            }).forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    返回此流元素组成的流

    /*
        中间操作
            返回此流元素组成的流:map()
            IntSteam mapToInt()   返回一个IntSteam类型的结果
     */
    public class Demo05 {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("10");
            list.add("20");
            list.add("30");
            list.add("40");
            list.add("50");
    
            //需求:将集合中的字符串数据转换为整数之后在控制台输出。
            System.out.println("====需求1====");
            list.stream().map(x->Integer.parseInt(x)).forEach(System.out::println);
            //以上方法可以改进。
            System.out.println("====需求1改进====");
            list.stream().map(Integer::parseInt).forEach(System.out::println);
            //以上方法还可以改进。
            System.out.println("====需求1再改进====");
            //用第3个
            list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
            //求和
            int sum = list.stream().mapToInt(Integer::parseInt).sum();
            System.out.println("求和:" + sum);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    3 终结操作

    输出

    /*
        终结操作
            输出:forEach()
            返回流中的元素数:count()
     */
    public class Demo06 {
        public static void main(String[] args) {
            //创建一个集合,存储多个字符串元素。
            List<String> list = new ArrayList<>();
    
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
    
            //需求1:把集合中的元素在控制台输出。
            System.out.println("====需求1====");
            list.stream().forEach(System.out::println);
            //需求2:统计集合中有几个以“张”开头的元素,并把统计结果在控制台输出。
            System.out.println("====需求2====");
            long count = list.stream().filter(x -> x.startsWith("张")).count();
            System.out.println(count);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    收集操作

    map只是把一个新的流转换为一个新的流,而collect的把流转换为集合。

    /*
        Stream流的收集操作
    
     */
    public class Demo08 {
        public static void main(String[] args) {
            //创建List集合对象
            List<String> list = new ArrayList<>();
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            //需求1:得到名字为3个字的流
            Stream<String> stream = list.stream().filter(x -> x.length() == 3);
            //需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历。
            List<String> collectList = stream.collect(Collectors.toList());
            System.out.println("=====List=====");
            for (String string : collectList) {
                System.out.println(string);
            }
    
            //创建Set集合对象。
            Set<Integer> set = new HashSet<>();
            set.add(10);
            set.add(20);
            set.add(30);
            set.add(40);
            //需求3:得到大于25的流
            Stream<Integer> integerStream = set.stream().filter(x -> x > 25);
            //需求4:把使用Stream流操作完毕的数据收集到Set集合中并遍历。
            Set<Integer> collectSet = integerStream.collect(Collectors.toSet());
            System.out.println("=====Set=====");
            //Set集合是无序的,输出无序。
            for (Integer integer : collectSet) {
                System.out.println(integer);
            }
    
            //定义一个字符串数组。
            String string[] = {"林青霞,1", "张曼玉,2", "王祖贤,3", "柳岩,4"};
            //需求5:得到字符串中数据大于2的流。
            Stream<String> stringStream = Stream.of(string).filter(x -> Integer.parseInt(x.split(",")[1]) > 2);
            //需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,序号作值。
            Map<String, Integer> integerMap = stringStream.collect(Collectors.toMap(x -> x.split(",")[0], x -> Integer.parseInt(x.split(",")[1])));
            Set<String> ketSet = integerMap.keySet();
            System.out.println("=====Map=====");
            for (String str : ketSet) {
                Integer value = integerMap.get(str);
                System.out.println(str + "=" + value);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    4 练习

    /*
        Stream流的练习
            现在有两个 ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
            1.男演员只要名字为3个字的前三人
            2.女演员只要姓林的,井且不要第一个
            3.把过滤后的男演员姓名和女演员姓名合并到一起
            4.把上一步操作后的元素作为构造方法的参数创建演员对象遍历数据
                演员类Actor已经提供,里面有一个成员变量,一个带参造方法,以及成员变量对应的 get/set方法
     */
    public class Demo01 {
        public static void main(String[] args) {
            //男演员集合
            List<String> manList = new ArrayList<>();
            manList.add("周润发");
            manList.add("成龙");
            manList.add("刘德华");
            manList.add("吴京");
            manList.add("周星驰");
            manList.add("李连杰");
            //女演员集合
            List<String> womanList = new ArrayList<>();
            womanList.add("林心如");
            womanList.add("张曼玉");
            womanList.add("林青霞");
            womanList.add("柳岩");
            womanList.add("林志玲");
            womanList.add("王祖贤");
    
            System.out.println("================方法1================");
            Stream<String> manListStream = manList.stream().filter(name -> name.length() == 3).limit(3);
            
            Stream<String> womanListStream = womanList.stream().filter(name -> name.startsWith("林")).skip(1);
            
            Stream<String> concatStream = Stream.concat(manListStream, womanListStream);
            
            concatStream.map(name -> new Actor(name)).forEach(System.out::println);
            // concatStream.map(Actor::new).forEach(System.out::println);
            
            System.out.println("================方法2================");
            Stream.concat(manList.stream().filter(x -> x.length() == 3).limit(3)
                    , womanList.stream().filter(x -> x.startsWith("林")).skip(1))
                    .map(Actor::new)
                    .forEach(System.out::println);
        }
    }
    
    class Actor {
        private String name;
    
        public Actor() {
        }
    
        public Actor(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Actor{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    参考资料:Java 8 Stream | 菜鸟教程 (runoob.com)

  • 相关阅读:
    Yolov5斜框检测tensorrt部署(C++)从入门到入坟
    deeplab实现自己遥感地质分割数据集
    与目前主流的消费返利平台对比,共享购模式有什么优势呢?
    Pinia(五)了解和使用plugin
    【Java毕设】基于SpringBoot实现新冠疫情统计系统(Idea+Navicat)
    用了这么久docker,今天才算是把容器数据卷搞清楚了
    Mybatis源码详解
    postman的使用
    springboot分布式锁实现(Redisson)
    Qt 鼠标右键菜单显示不超出屏幕底部
  • 原文地址:https://blog.csdn.net/qq_46095164/article/details/126227668