【Java】25 Stream 流

时间:2022-07-26
本文章向大家介绍【Java】25 Stream 流,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

在 JDK 1.8 中,得益于 Lambda 表达式所带来的函数式编程,引入了一个全新的 Stream 概念,用于解决已有集合类库既有的弊端。

1.1 初识 Stream

1.1.1 集合类库弊端

我们需要筛选出集合中元素包含“叁”的元素,但是我们却遍历了元素集合,这无疑是累赘的。

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("壹");
        list.add("贰");
        list.add("叁");
        list.add("肆");
        list.add("伍");

        List<String> tempList = new ArrayList<>();
        for (String name : list) {
            if (name.contains("叁")) {
                tempList.add(name);
            }
        }

        for (String s : tempList) {
            System.out.println(s);
        }
    }
}

1.1.2 Stream 更优写法

下述代码中并没有体现出遍历操作,我们可以更好地体现做什么而不是怎么做。

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("壹");
        list.add("贰");
        list.add("叁");
        list.add("肆");
        list.add("伍");

		// :: 方法引用,如果已有方法能够完成函数式接口中的功能,就可以使用方法引用替换 Lambda 
        list.stream().filter(s -> s.contains("叁")).forEach(System.out::println);
    }
}

1.1.3 Stream 概述

  Stream 是 JDK 1.8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用 Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。Stream 有如下特点:   ♞ 不是数据结构,不会保存数据。   ♞ 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。   ♞ 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。 Stream 就像是流水线上生产的产品,直到最后一步才会生成成品。


1.2 获取流

1.2.1 Collection 集合获取流

collection 集合可以通过 stream( ) 默认方法获取流

public class Demo {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        collection.add("壹");
        collection.add("贰");
        collection.add("叁");
        collection.add("肆");
        collection.add("伍");

        Stream<String> stream = collection.stream();
    }
}

1.2.2 数组获取流

数组通过 Stream 接口的静态方法 of( ) 获取流,基本数据类型数组不能使用 Stream.of( )。

public class Demo {
    public static void main(String[] args) {
        Integer[] array = {1, 2, 3, 4, 5};

        Stream<Integer> stream = Stream.of(array);
    }
}

1.3 操作符

  操作符就是对数据进行的一种处理工作,一道加工程序;就好像工厂的工人对流水线上的产品进行一道加工程序一样。Stream 的操作符分为两种:中间操作符和终止操作符。

1.3.1 中间操作符

操作符

说明

map( )

转换操作

limit( )

限流操作

distint( )

去重操作

filter( )

过滤操作

peek( )

挑出操作

skip( )

跳过操作

sorted( )

排序操作

concat( )

合并操作

转换操作

public class Demo {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3", "4", "5"};

        Stream.of(array).map(s -> Integer.parseInt(s))
        	.forEach(s -> System.out.println(s + "的类型是:" + s.getClass().getName()));
    }
}

限流操作

public class Demo {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3", "4", "5"};

        Stream.of(array).limit(3).forEach(System.out::println);
    }
}

去重操作

public class Demo {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3", "1", "1"};

        Stream.of(array).distinct().forEach(System.out::println);
    }
}

过滤操作

public class Demo {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3", "1", "1"};

        Stream.of(array).filter(s -> !"1".equals(s)).forEach(System.out::println);
    }
}

挑出操作

public class Demo {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3", "4", "5"};

        Stream.of(array).skip(3).peek(s -> System.out.println("peek --- " + s)).forEach(System.out::println);
    }
}

跳过操作

public class Demo {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3", "4", "5"};

        Stream.of(array).skip(3).forEach(System.out::println);
    }
}

排序操作

public class Demo {
    public static void main(String[] args) {
        String[] array = {"5", "2", "6", "1", "4"};

        Stream.of(array).sorted().forEach(System.out::println);
    }
}

合并操作

合并操作两个流的数据类型要一致

public class Demo {
    public static void main(String[] args) {
        String[] array = {"1", "2", "3", "4", "5"};

        List<String> list = new ArrayList<>();
        list.add("壹");
        list.add("贰");
        list.add("叁");
        list.add("肆");
        list.add("伍");

        Stream.concat(Stream.of(array), list.stream()).forEach(System.out::println);
    }
}

1.3.2 终止操作符

  终止操作符就是用来对数据进行收集或者消费的,数据到了终止操作这里就不会向下流动了,终止操作符只能使用一次。

操作符

说明

count

统计操作

forEach

遍历操作

toArray

数组操作

统计操作

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("壹");
        list.add("贰");
        list.add("叁");
        list.add("肆");
        list.add("伍");

        long count = list.stream().filter(s -> !"叁".equals(s)).count();
        System.out.println(count);
    }
}

遍历操作

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("壹");
        list.add("贰");
        list.add("叁");
        list.add("肆");
        list.add("伍");

        list.stream().filter(s -> !"叁".equals(s)).forEach(System.out::println);
    }
}

数组操作

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("壹");
        list.add("贰");
        list.add("叁");
        list.add("肆");
        list.add("伍");

        Object[] objects = list.stream().filter(s -> !"叁".equals(s)).toArray();
        System.out.println(Arrays.toString(objects));
    }
}

每个 Stream 流只能使用一次 Stream 流必须使用 终止操作符 否则不会有输出