Java 8 Stream

for-each 让你站起来,stream 让你飞起来

Strem

Stream (流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。Java中的 Stream 并不会存储元素,而是按需计算。
  • 数据源 流的来源。可以是集合,数组,I/O channel,产生器 generator 等。
  • 聚合操作 类似SQL语句一样的操作,比如 filter,map,reduce,find,match,sorted等。

和 Collection 操作不同,Stream操作还有两个基础的特征:

  • Pipelining:中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流试风格。这样做可以对操作进行优化,比如延迟执行和短链。
  • 内部迭代:以前对集合便利都是通过 Iterator 或者 for-each 的方式,显示的在集合外部进行迭代,这叫做外部迭代。Stream 提供了内部迭代的方式,通过访问者模式实现。

生成流

在 Java 8 中,集合接口有两个方法来生成流:

  • stream():为集合创建串行流。
  • parallelStream():为集合创建并行流。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

并行流是利用多个线程来处理数据的,因此,操作的执行顺序不再是固定的,而是依赖于线程的调度和任务的分配。但是 collect 会按照原始顺序收集

package org.example;

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        System.out.println("顺序流");
        numbers.stream().forEach(f -> System.out.print(f+" ")); // 打印结果);

        System.out.println();
        System.out.println("并行流");

        // 使用并行流
        numbers.parallelStream().forEach(f -> System.out.print(f+" "));
    }
}

运行结果

顺序流
1 2 3 4 5 
并行流
3 5 4 2 1 

forEach

forEach 用来迭代流中的每个数据。以下代码片段使用 forEach 输出集合元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.forEach(System.out::println);

map

map 方法用于映射每个元素到对应的结果,以下代码使用 map 输出了元素对应的 name :

List<User> userList = new ArrayList<>();
userList.add(new User(1,"张三"));
userList.add(new User(2,"李四"));
userList.add(new User(3,"王五"));

List<String> names = userList.stream().map(User::getName).collect(Collectors.toList());

filter

filter 方法用于通过设置的条件过滤出元素。以下代码使用 filter 方法过滤处空字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> result = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

limit

limit 方法用于获取指定数量的流。以下代码片段使用 limit 方法打印出 10 条数据:

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted

sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

Collectors

Collectors 类实现了很多规约操作,例如将流转化成集合和聚合元素,**collect 会按照原始顺序收集。**Collectors 可用于返回列表或字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

在转换为map时,需要使用 (existing,replacement)-> existring/replacement 防止键冲突报错。
在 key 冲突时保留旧值:

        Map<String, String> platformOPenIdMapPlatformUserId = platformUserIdMapPlatformOpenId.entrySet().stream()
                .filter(e -> StrUtil.isNotEmpty(e.getValue()))
                .collect(Collectors.toMap(
                        Map.Entry::getValue,
                        Map.Entry::getKey,
                        (existing,replacement) -> existing		
                        )); 

在 key 冲突时保留新值:

        Map<String, String> platformOPenIdMapPlatformUserId = platformUserIdMapPlatformOpenId.entrySet().stream()
                .filter(e -> StrUtil.isNotEmpty(e.getValue()))
                .collect(Collectors.toMap(
                        Map.Entry::getValue,
                        Map.Entry::getKey,
                        (existing,replacement) -> replacement		
                        )); 

### Java 8 Stream API 使用教程 #### 创建流 创建流的方式有多种,可以通过集合类的 `stream()` 方法获取流实例。 ```java List<String> list = Arrays.asList("apple", "banana", "orange"); Stream<String> stream = list.stream(); ``` 对于数组,则可以使用静态方法 `Arrays.stream` 或者 `Stream.of`. ```java String[] array = {"apple", "banana", "orange"}; Stream<String> streamFromArray = Arrays.stream(array); // or Stream<String> streamOfArray = Stream.of(array); ``` #### 中间操作 中间操作返回一个新的流对象,在此之后还可以继续调用其他的操作。常见的中间操作包括但不限于: - **filter**: 过滤掉不符合条件的元素[^1] ```java Stream<String> filteredStream = stream.filter(s -> s.startsWith("a")); ``` - **map**: 将每一个输入元素按照指定映射关系转换成另一个输出元素 ```java Stream<Integer> lengthStream = stream.map(String::length); ``` - **peek**: 对每个元素执行某些动作并传给下游,通常用于调试目的[^2] ```java Stream<String> peekedStream = stream.peek(System.out::println); ``` #### 终端操作 终端操作会触发实际计算过程,并关闭流。一旦执行了一个终端操作后就不能再对该流做任何进一步的操作了。一些常用的终端操作如下所示: - **forEach**: 遍历整个序列中的每一项 ```java stream.forEach(System.out::println); ``` - **collect(Collectors.toList())**: 收集结果到列表中 ```java List<String> resultList = stream.collect(Collectors.toList()); ``` - **count()**: 计算总数目 ```java long count = stream.count(); ``` 这些只是基础部分;实际上还有更多高级特性和组合方式等待探索。通过合理运用上述概念以及所提供的例子,应该能更好地理解如何利用Java Streams简化日常开发工作流程的同时提高效率和代码质量。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值