HHR的小站
享受代码带来的快乐吧
首页
Java Stream API 使用
2021-02-07 |HHR | 代码使人快乐, 语言的魅力

什么是Stream API

关于stream,IBM对其有一个概括。链接

Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。

怎么使用stream API

获得一个stream对象

对于实现了List接口的对象,获取stream非常简单。

        List<Integer> nums = new ArrayList<>();
        Stream<Integer> stream = nums.stream();

调用Liststream()方法,即可得到一个Stream对象。
而对于int[]一类的数组,获取stream也不是很困难。

        int[] nums = {1, 2, 3, 4, 5, 6, 7};
        IntStream stream = Arrays.stream(nums);

由于Java的基本数据类型导致的问题,此处的stream不再为Stream<T>类型(毕竟int并不是对象),而是一个所谓的IntStream,不过这并不影响其的使用。要获得Stream<Integer>类型的stream,我们只需要将数组更换为Integer[]类型。

        Integer[] nums = {1, 2, 3, 4, 5, 6, 7};
        Stream<Integer> stream = Arrays.stream(nums);

stream有什么用?

获得了一个stream对象之后,我们就可以开始利用它。

求数组长度

最简单的,调用stream.count()方法,即可获得数组的长度。

        Integer[] nums = {1, 2, 3, 4, 5, 6, 7};
        Stream<Integer> stream = Arrays.stream(nums);
        long size = Arrays.stream(nums).count();
        //上下两行代码等价
        size = nums.length;

有人可能会说,就这?这只是stream最简单的使用,接着来些好玩的例子。

统计不及格学生的学号

        Map<String, Integer> score = new HashMap<>();
        score.put("201806061100", 95);
        score.put("201806061101", 75);
        score.put("201806061102", 53);
        score.put("201806061103", 54);
        score.put("201806061104", 77);
        score.keySet().stream()
                .filter(key -> score.get(key) < 60)
                .forEach(key -> System.out.println(key));

该例子使用了stream的filter方法,其中使用了一个lambda表达式,传入一个key,返回key所对应的value是否小于60。这个filter会返回所有成绩低于60分的学生的学号。
接下来,使用了forEach方法,继续利用lambda表达式,将这些学号依次输出。

将stream转回List

        List<String> blame = score.keySet().stream()
                .filter(key -> score.get(key) < 60)
                .collect(Collectors.toList());

使用collect方法,指定转换方式为toList,即可将其转回List<String>

对值进行额外的处理

        score.keySet().stream()
                .filter(key -> score.get(key) < 60)
                .map(key -> key.substring(8))
                .forEach(key->System.out.println(key));

在这里,我们使用了一个新方法 map,可以将其解释为映射.map(key -> key.substring(8)),会返回一个新的stream对象,其中的每一项都执行了 .substring(8)的操作。

排序

        Map<String, Integer> score = new HashMap<>();
        score.put("201806061100", 95);
        score.put("201806061101", 75);
        score.put("201806061102", 53);
        score.put("201806061103", 54);
        score.put("201806061104", 77);
        score.keySet().stream()
                .sorted((k1, k2) -> score.get(k2) - score.get(k1))
                .forEach(key -> System.out.println(key));

使用 sorted方法,并在其中实现一个比较器,即可完成按照成绩从高到低的顺序进行排序。

更多有趣的方法

有关stream的方法还有很多,读者可自行进入Java的文档进行了解,本文不再进行介绍。

respond-post-510

添加新评论

请填写称呼
请填写合法的电子邮箱地址
请填写合法的网站地址
请填写内容