深入解析Java 8 Stream API:介绍与使用方法

一篇文章带你学会Java的stream

Java 8 引入了一系列重要的新特性,其中之一便是 Stream API。Stream API 是一个用于处理集合数据的强大工具,通过提供一种简洁、高效且易于并行化的方式来处理数据流,从而极大地简化了编写代码的复杂性。本文将深入探讨 Java 8 Stream API 的基本概念、使用方法以及实际应用。

以下是对stream的介绍,你可以根据文章中所提到的代码块,直接放到main方法中跑,可以直观的看出stream的神奇之处

一、什么是 Stream API?

1.1 基本概念

Stream API 是 Java 8 提供的一个新特性,它不是数据结构,而是关于数据计算的抽象。Stream 代表数据通道,可以在其中执行一系列操作来处理数据。其设计灵感来源于函数式编程,通过流操作可以对数据进行过滤、映射、规约等操作。

1.2 Stream 和传统集合的区别

传统集合框架(如 List、Set)主要关注数据的存储和访问,而 Stream 更关注数据的计算过程。集合是数据的静态存储,而 Stream 是数据的动态视图,通过一系列的操作(intermediate operations)和终端操作(terminal operations)进行计算。

二、Stream 的基本操作

2.1 创建 Stream

Stream 可以通过多种方式创建,常见的方法有:

  • 从集合创建
  • 从数组创建
  • 使用工厂方法(如 Stream.of) 生成无限流

2.1.1 从集合创建

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();

2.1.2 从数组创建

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

2.1.3 使用工厂方法

Stream<String> stream = Stream.of("a", "b", "c");

2.1.4 生成无限流

Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);

2.2 中间操作(Intermediate Operations)

中间操作是对流中的元素进行加工和转换,并生成一个新的流。常见的中间操作包括 filter、map、flatMap、distinct、sorted 和 peek。

2.2.1 filter(过滤)

filter 方法用于过滤符合条件的元素。

List<String> list = Arrays.asList("a", "b", "c", "d");
Stream<String> stream = list.stream().filter(s -> s.startsWith("a"));

2.2.2 map(分类)

map 方法用于将元素转换为另一种形式。


List<String> list = Arrays.asList("a", "b", "c", "d");
Stream<String> stream = list.stream().map(String::toUpperCase);

2.2.3 flatMap(分类)

flatMap 方法用于将每个元素转换为流,然后合并成一个新的流。

List<List<String>> listOfLists = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d"));
Stream<String> stream = listOfLists.stream().flatMap(Collection::stream);

2.2.4 distinct(去重)

distinct 方法用于去重。

List<String> list = Arrays.asList("a", "b", "a", "c");
Stream<String> stream = list.stream().distinct();

2.2.5 sorted(排序)

sorted 方法用于对元素进行排序。

List<String> list = Arrays.asList("d", "a", "c", "b");
Stream<String> stream = list.stream().sorted();

2.2.6 peek(监视)

peek 方法用于在中间操作中对每个元素执行某个动作。

List<String> list = Arrays.asList("a", "b", "c", "d");
Stream<String> stream = list.stream().peek(System.out::println);

2.3 终端操作(Terminal Operations)

终端操作是流的最后一步操作,它会触发流的处理,并产生最终的结果。常见的终端操作包括 forEach、collect、reduce、count、anyMatch、allMatch 和 noneMatch。

2.3.1 forEach(遍历)

forEach 方法用于对流中的每个元素执行某个动作。

List<String> list = Arrays.asList("a", "b", "c", "d");
list.stream().forEach(System.out::println);

2.3.2 collect(收集)

collect 方法用于将流中的元素收集到集合中。

List<String> list = Arrays.asList("a", "b", "c", "d");
List<String> result = list.stream().collect(Collectors.toList());

2.3.3 reduce(重组)

reduce 方法用于将流中的元素组合成一个结果。

List<Integer> list = Arrays.asList(1, 2, 3, 4);
int sum = list.stream().reduce(0, Integer::sum);

2.3.4 count(计数)

count 方法用于计算流中的元素个数。

List<String> list = Arrays.asList("a", "b", "c", "d");
long count = list.stream().count();

2.3.5 anyMatch(判断 任一)

anyMatch 方法用于判断是否有任意一个元素满足条件。

List<String> list = Arrays.asList("a", "b", "c", "d");
boolean anyMatch = list.stream().anyMatch(s -> s.equals("a"));

2.3.6 allMatch(判断 全部)

allMatch 方法用于判断是否所有元素都满足条件。

List<String> list = Arrays.asList("a", "b", "c", "d");
boolean allMatch = list.stream().allMatch(s -> s.length() == 1);

2.3.7 noneMatch(判断 非)

noneMatch 方法用于判断是否没有元素满足条件。

List<String> list = Arrays.asList("a", "b", "c", "d");
boolean noneMatch = list.stream().noneMatch(s -> s.length() > 1);

三、并行流(Parallel Stream)

Stream API 提供了对流进行并行处理的能力,通过 parallelStream 方法或 parallel 方法,可以轻松地将流转换为并行流。

3.1 使用 parallelStream

List<String> list = Arrays.asList("a", "b", "c", "d");
list.parallelStream().forEach(System.out::println);

3.2 使用 parallel 方法

List<String> list = Arrays.asList("a", "b", "c", "d");
list.stream().parallel().forEach(System.out::println);

3.3 并行流的性能考虑

虽然并行流可以提升性能,但并不是所有情况下都适用。使用并行流时需要考虑以下几点:

  • 数据量:并行流适用于大数据量处理,数据量较小时,并行化的开销可能超过其带来的性能提升。
  • 数据结构:某些数据结构(如 ArrayList)在并行流中表现更好,而另一些(如 LinkedList)则可能不适合。
  • 算法复杂度:复杂度较高的操作可能更适合并行流,但需要确保线程安全。

四、Stream API 实际应用

4.1 数据过滤与转换

List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
List<String> result = list.stream()
    .filter(s -> s.startsWith("a"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());
System.out.println(result);

4.2 数据分组与统计

List<String> list = Arrays.asList("apple", "banana", "cherry", "date", "apricot");
Map<Character, List<String>> groupedByFirstLetter = list.stream()
    .collect(Collectors.groupingBy(s -> s.charAt(0)));
System.out.println(groupedByFirstLetter);

4.3 查找最大值和最小值

List<Integer> list = Arrays.asList(10, 20, 30, 40);
int max = list.stream().max(Integer::compare).orElseThrow(NoSuchElementException::new);
int min = list.stream().min(Integer::compare).orElseThrow(NoSuchElementException::new);
System.out.println("Max: " + max + ", Min: " + min);

4.4 数据聚合

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream().reduce(0, Integer::sum);
System.out.println("Sum: " + sum);

4.5 并行流应用示例

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.parallelStream().reduce(0, Integer::sum);
System.out.println("Sum (parallel): " + sum);

五、Stream API 的高级特性

5.1 自定义收集器

Stream API 提供了 Collector 接口,允许用户自定义收集逻辑。

List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
Collector<String, StringJoiner, String> customCollector = Collector.of(
    () -> new StringJoiner(", "),
    StringJoiner::add,
    StringJoiner::merge,
    StringJoiner::toString
);
String result = list.stream().collect(customCollector);
System.out.println(result);

5.2 使用流构建器

Stream API 提供了 Stream.Builder 类,允许用户逐步构建流。

Stream.Builder<String> builder = Stream.builder();
builder.add("a").add("b").add("c");
Stream<String> stream = builder.build();
stream.forEach(System.out::println);

5.3 流的短路操作

某些操作(如 anyMatch、allMatch、noneMatch、findFirst、findAny)是短路操作,即在条件满足后会立即结束处理,不再处理剩余元素。

List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
boolean anyMatch = list.stream().anyMatch(s -> s.startsWith("a"));
System.out.println("Any match: " + anyMatch);

六、结论

Java 8 的 Stream API 是一个强大的工具,为数据处理提供了简洁、高效的方式。通过理解 Stream 的基本概念和操作方法,我们可以编写出更加简洁和高效的代码。尽管 Stream 提供了很多便利,但在使用过程中仍需注意性能和可读性,确保代码不仅高效,而且易于维护。

希望本文能帮助你更好地理解和使用 Java 8 的 Stream API,并在实际开发中充分发挥其优势。

  • 18
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值