当前位置:首页 » 《关于电脑》 » 正文

Java中Stream流详解

21 人参与  2024年11月12日 16:01  分类 : 《关于电脑》  评论

点击全文阅读


文章目录

概要✨介绍?特点?操作类型?优缺点 获取Steam流获取List集合的Stream流获取Set集合的Stream流获取Map集合的流获取数组的Stream流 Stream的方法filter:根据给定的条件过滤出符合条件的元素。map:将每个元素通过给定的函数映射成另一个元素(对每一项数据进行加工处理)。peek:对流中的每个元素执行操作并返回一个新的流,主要用于调试。sorted:对Stream中的元素进行排序。distinct:去除Stream中的重复元素。reduce:对Stream中的元素进行归约操作,可以实现求和、求最大值、求最小值等操作。limit:限制Stream中元素的数量。skip:跳过Stream中的前几个元素。anyMatch:检查Stream中是否有满足给定条件的元素。allMatch:检查Stream中的所有元素是否都满足给定条件。noneMatch:检查Stream中的所有元素是否都不满足给定条件。findFirst:返回Stream流中的第一个元素。findAny:返回Stream中的任意一个元素。count:返回Stream中的元素数量。max:返回Stream中的最大值。min:返回Stream中的最小值。 小结

概要

✨介绍

Java中的Stream是Java 8引入的一种新的API,用于处理集合或数组中的数据,提供了一种简洁且高效的方式来进行各种操作,如过滤、排序、映射、汇总等。Stream不存储数据,它更像是一个高级迭代器,通过一系列流水线操作来处理数据。Stream操作可以分为两类:中间操作和终端操作

?特点

惰性求值 (Lazy Evaluation):Stream中的操作是惰性执行的,只有在终止操作执行时,才会实际计算结果。不可变性 (Immutability):Stream是不可变的,每次对Stream的操作都会返回一个新的Stream,而不会修改原始数据源。无存储 (No Storage):Stream不会存储数据,数据存储在数据源中。

?操作类型

中间操作 (Intermediate Operations):返回一个新的Stream,允许多个操作链式调用。这些操作都是惰性执行的,直到执行终止操作。

常见的中间操作包括:filter(), map(), sorted(), distinct(), limit(), skip(), peek()等。

终止操作 (Terminal Operations):触发Stream的处理并生成结果。终止操作会关闭Stream,使得Stream无法再被使用。

常见的终止操作包括:forEach(), collect(), reduce(), count(), min(), max(), anyMatch(), allMatch(), noneMatch()等。

?优缺点

优点:

代码简洁性与可读性:Stream 提供了声明式的编程方式,使得代码更简洁、优雅。可以通过链式调用将复杂的操作步骤清晰地表达出来,减少了样板代码(如循环和条件判断)的使用。函数式编程支持:Stream 强化了Java对函数式编程的支持。开发者可以将Lambda表达式与Stream结合,使用map、filter、reduce等操作处理数据,这种方式更加直观且容易维护。并行处理能力:Stream 支持并行流(parallelStream),允许在多核处理器上并行处理数据,提升处理性能,特别适合大规模数据处理的场景。惰性求值:Stream 的惰性求值特性可以优化性能。只有在终止操作执行时,Stream 才会真正执行操作。这使得可以将多个中间操作组合起来,并且只需遍历数据源一次,减少不必要的计算。流畅的API设计:Stream API 设计非常流畅,提供了多种常用操作,可以很方便地组合这些操作来实现各种复杂的数据处理逻辑。

缺点:

调试困难:由于Stream使用了链式调用和Lambda表达式,调试过程比传统的for循环复杂得多。特别是在链式操作中出现错误时,定位问题可能较为困难。性能开销:虽然Stream可以通过并行处理提升性能,但在某些场景下,它的性能可能低于传统的循环。例如,在涉及大量对象创建或短小集合的场景中,Stream的惰性求值和中间对象的创建可能带来额外的性能开销。可读性问题:虽然Stream可以使代码更加简洁,但过度使用或在不适合的场合使用Stream可能导致代码过于复杂,降低可读性,特别是对于不熟悉Stream的开发者而言。资源消耗:在某些情况下,Stream 可能导致较高的内存消耗。例如,如果在一个非常大的集合上使用复杂的流操作链,可能会占用大量内存,甚至导致OutOfMemoryError。不适合所有场景:Stream 更适合处理无状态的、不可变的数据操作。对于需要频繁修改数据或需要处理具有状态的操作,传统的迭代方法可能更为合适。
package com.stream;import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.stream.Collectors;/*** 需求:找出姓张,并且是3个字的名字,存入到一个新集合中*/public class Demo {    public static void main(String[] args) {        ArrayList<String> names = new ArrayList<>();        Collections.addAll(names, "张三丰", "张无忌", "周芷若", "赵敏", "张三", "韦一笑");        // 方案一:传统遍历        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> list2 = names.stream()                .filter(name -> name.startsWith("张") && name.length() == 3)                .collect(Collectors.toList());        System.out.println(list2); // [张三丰, 张无忌]    }}

获取Steam流

获取List集合的Stream流

ArrayList<String> names = new ArrayList<>();Collections.addAll(names, "张三丰", "张无忌", "周芷若", "赵敏", "张三", "韦一笑");Stream<String> stream = names.stream();

获取Set集合的Stream流

Set<String> set = new HashSet<>();Collections.addAll(set, "九阳神功", "乾坤大挪移", "九阴白骨爪", "峨眉剑法");Stream<String> stream1 = set.stream();

获取Map集合的流

Map<String, Integer> map = new HashMap<>();map.put("李白", 521);map.put("杜甫", 412);map.put("白居易", 243);map.put("陶渊明", 156);// map keys 的 StreamSet<String> strings = map.keySet();Stream<String> stream2 = strings.stream();// Map values 的 StreamCollection<Integer> values = map.values();Stream<Integer> stream3 = values.stream();Set<Map.Entry<String, Integer>> entries = map.entrySet();Stream<Map.Entry<String, Integer>> kvs = entries.stream();kvs.filter(v -> v.getKey().contains("白")).forEach(i -> System.out.println(i.getKey() + ": " + i.getValue()));

获取数组的Stream流

String[] names2 = {"薛平贵", "王宝钏", "葛青", "葛大", "张伟"};Stream<String> stream4 = Arrays.stream(names2);Stream<String> stream5 = Stream.of(names2);
package com.stream;import java.util.*;import java.util.stream.Collectors;import java.util.stream.Stream;public class Demo0 {    public static void main(String[] args) {        // 一、获取List集合的Stream流        ArrayList<String> names = new ArrayList<>();        Collections.addAll(names, "张三丰", "张无忌", "周芷若", "赵敏", "张三", "韦一笑");        Stream<String> stream = names.stream();        // 二、获取Set集合的Stream流        Set<String> set = new HashSet<>();        Collections.addAll(set, "九阳神功", "乾坤大挪移", "九阴白骨爪", "峨眉剑法");        Stream<String> stream1 = set.stream();        // 三、获取Map集合的流        Map<String, Integer> map = new HashMap<>();        map.put("李白", 521);        map.put("杜甫", 412);        map.put("白居易", 243);        map.put("陶渊明", 156);        // map keys 的 Stream        Set<String> strings = map.keySet();        Stream<String> stream2 = strings.stream();        // Map values 的 Stream        Collection<Integer> values = map.values();        Stream<Integer> stream3 = values.stream();        Set<Map.Entry<String, Integer>> entries = map.entrySet();        Stream<Map.Entry<String, Integer>> kvs = entries.stream();        kvs.filter(v -> v.getKey().contains("白"))                .forEach(i -> System.out.println(i.getKey() + ": " + i.getValue()));        // 四、获取数组的Stream流        String[] names2 = {"薛平贵", "王宝钏", "葛青", "葛大", "张伟"};        Stream<String> stream4 = Arrays.stream(names2);        Stream<String> stream5 = Stream.of(names2);        List<String> collect = stream5.filter(v -> v.length() == 3).collect(Collectors.toList());        for (String s : collect) {            System.out.println(s);        }    }}

Stream的方法

filter:根据给定的条件过滤出符合条件的元素。

public static void filter() {    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);    List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());    System.out.println(evenNumbers); // [2, 4]}

map:将每个元素通过给定的函数映射成另一个元素(对每一项数据进行加工处理)。

public static void map() {List<String> words = Arrays.asList("hello", "world", "java");List<Integer> wordLengths = words.stream().map(String::length).collect(Collectors.toList());System.out.println(wordLengths); // [5, 5, 4]}

peek:对流中的每个元素执行操作并返回一个新的流,主要用于调试。

public static void map() {Stream<String> stream = Stream.of("apple", "banana", "cherry");Stream<String> peekedStream = stream.peek(System.out::println); // "apple", "banana", "cherry"}

sorted:对Stream中的元素进行排序。

public static void sorted() {List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);   List<Integer> sortedNumbers = numbers.stream().sorted((a, b) -> a - b)       .collect(Collectors.toList());System.out.println(sortedNumbers); // [3, 5, 6, 7, 8]}

distinct:去除Stream中的重复元素。

public static void distinct() {List<String> daxias = Arrays.asList("张无忌", "赵敏", "张无忌", "周芷若", "赵敏");List<String> distinctDaxias = daxias.stream().distinct()        .collect(Collectors.toList()); // [张无忌, 赵敏, 周芷若]System.out.println(distinctDaxias);}

reduce:对Stream中的元素进行归约操作,可以实现求和、求最大值、求最小值等操作。

public static void reduce() {List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);    // 求和    Integer sum1 = numbers.stream().reduce((a, b) -> a + b).get();    Integer sum2 = numbers.stream().reduce(Integer::sum).get();    System.out.println("sum1: " + sum1 + ",sum2:" + sum2); // sum1: 29,sum2:29    // 最大值    Integer max1 = numbers.stream().reduce((a, b) -> a > b ? a : b).get();    Integer max2 = numbers.stream().reduce(Integer::max).get();    System.out.println("max1:" + max1 + ",max2:" + max2); // max1:8,max2:8// 最小值    Integer min1 = numbers.stream().reduce((a, b) -> a < b ? a : b).get();    Integer min2 = numbers.stream().reduce(Integer::min).get();    System.out.println("min1:" + min1 + ",min2:" + min2); // min1:3,min2:3}

limit:限制Stream中元素的数量。

public static void limit() {List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);    List<Integer> limitedNumbers = numbers.stream().limit(3).collect(Collectors.toList());System.out.println(limitedNumbers); // [8, 3, 6]}

skip:跳过Stream中的前几个元素。

public static void skip() {List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);    List<Integer> limitedNumbers = numbers.stream()    .skip(2)    .collect(Collectors.toList());    System.out.println(limitedNumbers); // [6, 7, 5]}

anyMatch:检查Stream中是否有满足给定条件的元素。

public static void anyMatch() {List<String> daxia = Arrays.asList("张无忌", "赵敏", "宋青书", "周芷若", "张三丰", "韦一笑");boolean isWiyixiao = daxia.stream().anyMatch("韦一笑"::equals);boolean isSongqingshu = daxia.stream().anyMatch("宋青书"::equals);    boolean isXiexun = daxia.stream().anyMatch("谢逊"::equals);    System.out.println(isWiyixiao);    // true    System.out.println(isSongqingshu); // true    System.out.println(isXiexun);      // false}

allMatch:检查Stream中的所有元素是否都满足给定条件。

public static void allMatch() {    List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);        boolean isAllLesstheTen = numbers.stream().allMatch(v -> v < 10);    boolean isAllLesstheFive = numbers.stream().allMatch(v -> v < 5);System.out.println(isAllLesstheTen);  // true    System.out.println(isAllLesstheFive); // false}

noneMatch:检查Stream中的所有元素是否都不满足给定条件。

public static void noneMatch() {    List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);        boolean noneMatch1 = numbers.stream().noneMatch(v -> v > 10);    boolean noneMatch2 = numbers.stream().noneMatch(v -> v > 5);    System.out.println(noneMatch1); // true    System.out.println(noneMatch2); // false}

findFirst:返回Stream流中的第一个元素。

public static void findFirst() {    List<String> daxia = Arrays.asList("张无忌", "赵敏", "宋青书", "周芷若", "张三丰", "韦一笑");        String firstEle = daxia.stream().findFirst().get();    System.out.println(firstEle); // 张无忌}

findAny:返回Stream中的任意一个元素。

public static void findAny() {    List<String> daxia = Arrays.asList("张无忌", "赵敏", "宋青书", "周芷若", "张三丰", "韦一笑");        String anyEle = daxia.stream().findAny().get();    System.out.println(anyEle); // 张无忌}

count:返回Stream中的元素数量。

public static void count() {    ArrayList<Integer> numbers = new ArrayList<>();    for (int i = 0; i < 100000; i++) {        numbers.add(i);    }    long count = numbers.stream().count();    System.out.println("集合总长度为:" + count); // 集合总长度为:100000}

max:返回Stream中的最大值。

public static void max() {    List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);        Integer maxValue = numbers.stream().max((a, b) -> a - b).get();    System.out.println(maxValue); // 8}

min:返回Stream中的最小值。

public static void min() {    List<Integer> numbers = Arrays.asList(8, 3, 6, 7, 5);    Integer maxValue = numbers.stream().min((a, b) -> a - b).get();System.out.println(maxValue); // 3}

小结

通过使用Stream,Java开发者可以以一种更简洁、清晰和高效的方式处理数据集,极大地提高了代码的可读性和可维护性。但是项目开发中要注意以下事项:

避免过度使用: 虽然Stream非常强大,但也要避免滥用,特别是在简单的情况下,可能会导致代码可读性下降。性能考虑: 在处理小数据集时,Stream的性能可能不如传统的循环,因此在使用时应根据具体场景选择合适的工具。

点击全文阅读


本文链接:http://zhangshiyu.com/post/185151.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1