Java中的stream流

本文介绍了Java8中Stream流的概念、特点、优点,包括简化集合操作、并行处理等,同时也讨论了其缺点和使用时的注意事项,提供代码实例以展示如何操作自定义类的集合和数组。
摘要由CSDN通过智能技术生成

目录

什么是stream流

Stream流的特点包括:

Stream流的优点:

Stream流的缺点:

Stream流的注意事项

 如何获取stream流

从集合获取:

从数组获取:

从文件获取:

常见的Stream中间方法(Intermediate Operations)包括:

常见的Stream终结方法(Terminal Operations)包括:

代码实例

 从集合获取Stream流,并对自定义类进行操作:

从数组获取Stream流,并对自定义类进行操作:


什么是stream流

在Java中,Stream流是Java 8引入的一种新的抽象概念,它允许对集合(Collection)对象进行函数式风格的操作。Stream可以让你以一种声明式的方式处理数据集合,而不用关心底层的实现细节。

Stream流的特点包括:

  1. 惰性求值(Lazy Evaluation):Stream操作会延迟执行,只有当需要结果时才会触发执行。这种惰性求值的特性可以提高性能,因为只有在需要时才会进行计算。

  2. 支持链式操作(Chainable Operations):可以将多个操作连接起来形成一个操作链,从而简化代码,提高可读性。

  3. 内部迭代(Internal Iteration):与传统的集合迭代方式相比,Stream流采用内部迭代的方式,可以更加灵活地对数据进行处理。

  4. 不可变性(Immutability):Stream操作不会修改原始数据,而是返回一个新的Stream,这样可以确保数据的不可变性,减少了并发环境下的问题。

Stream流的优点:

  • 简化集合操作:Stream提供了丰富的API,可以轻松地进行过滤、映射、排序等操作,大大简化了集合操作的代码。
  • 更具表现力:函数式风格的Stream操作使得代码更具表现力和可读性。
  • 并行处理支持:Stream提供了并行处理的支持,可以充分利用多核处理器的优势,提高程序的性能。

Stream流的缺点:

  • 学习曲线较陡:对于初学者来说,学习Stream的概念可能需要一定的时间和精力。
  • 性能开销:在一些简单的情况下,使用Stream可能会引入一些额外的性能开销,尤其是在数据量较小的情况下。
  • 不易调试:由于Stream操作是惰性求值的,当出现问题时,可能比较难以调试。

Stream流的注意事项

  1. 避免使用无限流:使用Stream.generate()Stream.iterate()等方法创建的流可能是无限的,需要谨慎使用以避免出现内存溢出等问题。

  2. 考虑并行流的适用性:虽然并行流可以提高处理速度,但并不是所有情况下都适用。对于简单的操作或者数据量较小的情况,使用并行流可能会带来额外的性能开销。因此,需要根据具体情况权衡是否使用并行流。

  3. 避免副作用:尽量避免在Stream操作中引入副作用(如修改外部变量、进行I/O操作等),这会使代码难以理解和调试,并可能引发并发安全问题。

  4. 处理异常:在对流进行操作时,可能会出现一些异常情况,需要在合适的地方进行异常处理。

  5. 考虑性能:虽然Stream提供了便利的操作方式,但在一些性能要求较高的场景下,可能需要考虑使用传统的迭代方式来替代Stream操作,以提高性能。

  6. 理解操作的顺序:Stream操作是按照声明的顺序依次执行的,需要确保操作的顺序符合预期。

  7. 不可重用:Stream流是单次使用的,一旦对流进行操作,就不能再次使用同一个流对象。如果需要多次操作相同的数据集合,需要创建新的流对象。

  8. 合理使用中间操作和终端操作:Stream操作分为中间操作和终端操作两种类型,中间操作用于构建操作链,而终端操作会触发实际的计算。合理使用这两种操作可以提高代码的可读性和性能。

 如何获取stream流

从集合获取

可以通过集合的stream()方法获取Stream流。

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
从数组获取

可以使用Arrays.stream()方法将数组转换为Stream流。

String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
从文件获取

可以使用Files.lines()方法读取文件内容并返回一个包含文件行的Stream流。 

try (Stream<String> stream = Files.lines(Paths.get("filename.txt"))) {
    // 在这里使用文件流进行操作
} catch (IOException e) {
    e.printStackTrace();
}

常见的Stream中间方法(Intermediate Operations)包括:

  1. filter(Predicate):根据指定的条件过滤流中的元素。

  2. map(Function):将流中的每个元素映射为另一个元素。

  3. sorted() / sorted(Comparator):对流中的元素进行排序,可以指定自定义的比较器。

  4. distinct():去除流中重复的元素。

  5. limit(long):截断流,使其最多只包含指定数量的元素。

  6. skip(long):跳过指定数量的元素,返回剩余的元素流。

  7. flatMap(Function):将流中的每个元素转换为一个流,然后将这些流合并为一个流。

  8. peek(Consumer):对流中的每个元素执行操作,同时保留流的原始元素。

常见的Stream终结方法(Terminal Operations)包括:

  1. forEach(Consumer):对流中的每个元素执行指定的操作。

  2. collect(Collector):将流中的元素收集到一个集合中。

  3. count():返回流中的元素数量。

  4. anyMatch(Predicate) / allMatch(Predicate) / noneMatch(Predicate):检查流中是否存在任意、所有或者没有元素满足指定条件。

  5. findFirst() / findAny():返回流中的第一个或者任意一个元素。

  6. reduce():对流中的元素进行归约操作,返回一个结果。

  7. min(Comparator) / max(Comparator):返回流中的最小或者最大元素。

  8. toArray():将流中的元素转换为数组。

代码实例

 从集合获取Stream流,并对自定义类进行操作:


这个示例演示了如何从一个包含自定义类(Person)对象的集合中获取Stream流,并对这些对象进行操作。具体来说:
        1.自定义了一个 Person 类,其中包含姓名(name)和年龄(age)属性。
        2.创建了一个包含几个 Person 对象的列表。
        3.使用 stream() 方法从列表中获取一个 Stream 流。
        4. 使用中间方法 filter() 过滤出年龄大于30的人。
        5.使用中间方法 map() 将 Person 对象映射为姓名字符串。
        6.使用终结方法 collect() 将结果收集到一个新的列表中。
        7.打印结果,显示年龄大于30的人的姓名列表。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class StreamExample1 {
    public static void main(String[] args) {
        // 从集合获取Stream流
        List<Person> people = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Charlie", 35)
        );
        System.out.println("Original list: " + people);

        // 使用中间方法和终结方法
        List<String> namesOver30 = people.stream()
                .filter(person -> person.getAge() > 30) // 过滤年龄大于30的人
                .map(Person::getName) // 获取姓名
                .collect(Collectors.toList()); // 收集结果到List中

        // 打印结果
        System.out.println("Names of people over 30: " + namesOver30);
    }
}
从数组获取Stream流,并对自定义类进行操作:


这个示例演示了如何从一个包含自定义类(Point)对象的数组中获取 Stream 流,并对这些对象进行操作。具体来说:
        1.自定义了一个 Point 类,表示二维平面中的一个点,包含 x 和 y 坐标。
        2.创建了一个包含几个 Point 对象的数组。
        3.使用 Stream.of() 方法从数组中获取一个 Stream 流。
        4.使用中间方法 filter() 过滤出 x 坐标大于2的点。
        5.使用中间方法 map() 对符合条件的点进行坐标翻倍。
        6.使用终结方法 forEach() 对结果进行遍历,并打印每个点的坐标。

import java.util.stream.Stream;

class Point {
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public String toString() {
        return "(" + x + ", " + y + ")";
    }
}

public class StreamExample2 {
    public static void main(String[] args) {
        // 从数组获取Stream流
        Point[] points = {
                new Point(1, 2),
                new Point(3, 4),
                new Point(5, 6)
        };

        // 使用中间方法和终结方法
        Stream.of(points)
                .filter(point -> point.getX() > 2) // 过滤x大于2的点
                .map(point -> new Point(point.getX() * 2, point.getY() * 2)) // 坐标翻倍
                .forEach(System.out::println); // 打印结果
    }
}

 

  • 37
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值