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
));