Stream流的常用方法
文章标签:
#java
一、获取流(创建 Stream 实例)
流的数据源 可以是集合、数组、值序列等,以下是常见的获取流的方式:
- 从集合获取流
所有 Collection 接口的实现类(如 List、Set)都可以通过 stream() 或 parallelStream() 方法获取流:
stream():返回串行流(单线程处理)。
parallelStream():返回并行流(多线程处理,适合大数据量)。
示例:
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> serialStream = list.stream(); // 串行流
Stream<String> parallelStream = list.parallelStream(); // 并行流
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
Stream<Integer> setStream = set.stream(); // Set 也能获取流
java
2. 从数组获取流
通过 Arrays.stream(array) 方法将数组转换为流:
示例:
int[] intArray = {1, 2, 3, 4};
IntStream intStream = Arrays.stream(intArray); // 基本类型流(IntStream)
String[] strArray = {"x", "y", "z"};
Stream<String> strStream = Arrays.stream(strArray); // 对象流
java
3. 直接创建流(值序列)
通过 Stream.of() 直接传入值创建流,支持可变参数:
示例:
Stream<Integer> numStream = Stream.of(1, 2, 3, 4); // 整数流
Stream<String> strStream = Stream.of("hello", "world"); // 字符串流
java
4. 创建空流
通过 Stream.empty() 创建空流(避免 null 导致的异常):
示例:
Stream<String> emptyStream = Stream.empty();
System.out.println(emptyStream.count()); // 输出:0(空流元素数为0)
java
5. 无限流(特殊场景)
通过 Stream.generate() 或 Stream.iterate() 创建无限流(需配合 limit() 限制长度):
示例:
// 生成10个随机数(无限流+limit限制)
Stream<Double> randomStream = Stream.generate(Math::random).limit(10);
randomStream.forEach(System.out::println);
// 从0开始,生成10个偶数(迭代生成)
Stream<Integer> evenStream = Stream.iterate(0, n -> n + 2).limit(10);
evenStream.forEach(System.out::println); // 0, 2, 4, ..., 18
java
二、中间操作(链式处理数据,返回新流)
中间操作不会立即执行,仅在终端操作触发时才会实际计算。
- filter(Predicate predicate)
功能:保留满足条件(predicate 返回 true)的元素。示例:筛选年龄大于 18 的用户:
List<User> users = Arrays.asList(
new User("张三", 20),
new User("李四", 17),
new User("王五", 25)
);
users.stream()
.filter(u -> u.getAge() > 18) // 保留成年人
.forEach(u -> System.out.println(u.getName())); // 输出:张三、王五
- map(Function<T, R> mapper)
功能:将元素转换为另一种类型(如提取字段、类型转换)。示例:将用户列表转换为姓名列表:
List<String> names = users.stream()
.map(User::getName) // 提取name属性(等价于 u -> u.getName())
.collect(Collectors.toList()); // 收集结果
System.out.println(names); // [张三, 李四, 王五]
- flatMap(Function<T, Stream> mapper)
功能:将每个元素转换为子流,再合并 为单个流(解决 “流中流” 问题)。示例:处理嵌套集合
List<List<String>> nestedList = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d")
);
// 使用 flatMap 展平为单层流
List<String> flatList = nestedList.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// 结果: ["a", "b", "c", "d"]
List<String> sentences = Arrays.asList("hello world", "java stream");
// 将每个句子分割成单词并合并
List<String> words = sentences.stream()
.flatMap(sentence -> Arrays.stream(sentence.split(" ")))
.collect(Collectors.toList());
// 结果: ["hello", "world", "java", "stream"]
- sorted() / sorted(Comparator comparator)
功能:排序。sorted() 用自然排序(元素需实现 Comparable);sorted(comparator) 用自定义比较器。示例:
// 自然排序(整数默认升序)
List<Integer> nums = Arrays.asList(3, 1, 2);
nums.stream().sorted().forEach(System.out::println); // 1、2、3
// 自定义排序(按字符串长度降序)
List<String> strs = Arrays.asList("apple", "cat", "banana");
strs.stream()
.sorted((s1, s2) -> Integer.compare(s2.length(), s1.length()))
.forEach(System.out::println); // banana(6)、apple(5)、cat(3)
- distinct()
功能:去重(基于元素的 equals() 方法)。示例:去除列表中的重复元素:
List<Integer> nums = Arrays.asList(1, 2, 2, 3, 3, 3);
nums.stream().distinct().forEach(System.out::println); // 1、2、3
- limit(long maxSize)
功能:截取前 maxSize 个元素(元素不足则取全部)。示例:取列表前 2 个元素:
List<String> list = Arrays.asList("a", "b", "c", "d");
list.stream().limit(2).forEach(System.out::println); // a、b
- skip(long n)
功能:跳过前 n 个元素(元素不足则返回空流)。示例:跳过前 2 个元素,取剩余元素:
List<String> list = Arrays.asList("a", "b", "c", "d");
list.stream().skip(2).forEach(System.out::println); // c、d
- peek(Consumer action)
功能:对元素执行操作(如打印、修改状态),但不改变流的内容(常用于调试)。示例:调试流处理过程:
List<Integer> nums = Arrays.asList(1, 2, 3);
nums.stream()
.peek(n -> System.out.println("原始值:" + n)) // 打印原始值
.map(n -> n * 2) // 转换为2倍
.peek(n -> System.out.println("转换后:" + n)) // 打印转换后的值
.collect(Collectors.toList()); // 触发执行
// 输出:
// 原始值:1
// 转换后:2
// 原始值:2
// 转换后:4
// 原始值:3
// 转换后:6
三、终端操作(触发计算,返回结果)
终端操作执行后,流会被 “消费”,无法再次使用。
- forEach(Consumer action)
功能:遍历元素并执行操作(如打印)。示例:打印列表元素:
List<String> list = Arrays.asList("a", "b", "c");
list.stream().forEach(System.out::println); // a、b、c
- collect(Collector<T, A, R> collector)
功能:将流收集到集合或其他结构(最常用的终端操作)。常用收集器:
Collectors.toList():收集到 List。
Collectors.toSet():收集到 Set(去重)。
Collectors.toMap():收集到 Map(需指定 key 和 value)。
Collectors.joining():拼接字符串。
示例:
// 收集到List
List<String> list = Stream.of("a", "b").collect(Collectors.toList());
// 收集到Set(去重)
List<Integer> nums = Arrays.asList(1, 2, 2, 3);
Set<Integer> set = nums.stream().collect(Collectors.toSet()); // {1, 2, 3}
// 收集到Map(key为姓名,value为年龄)
Map<String, Integer> userMap = users.stream()
.collect(Collectors.toMap(User::getName, User::getAge));
// 拼接字符串(用逗号分隔)
String joined = Stream.of("a", "b", "c").collect(Collectors.joining(","));
System.out.println(joined); // a,b,c
- count()
功能:返回元素数量(long 类型)。示例:统计偶数的数量:
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
long evenCount = nums.stream().filter(n -> n % 2 == 0).count();
System.out.println(evenCount); // 2(2和4是偶数)
- findFirst()
功能:返回第一个元素(包装在 Optional 中,避免 null)。示例:获取第一个偶数:
Optional<Integer> firstEven = nums.stream()
.filter(n -> n % 2 == 0)
.findFirst();
firstEven.ifPresent(System.out::println); // 2(若存在则打印)
- findAny()
功能:返回任意一个元素(并行流中效率更高,结果不确定)。示例:并行流中获取任意偶数:
Optional<Integer> anyEven = nums.parallelStream()
.filter(n -> n % 2 == 0)
.findAny();
anyEven.ifPresent(System.out::println); // 可能输出2或4
- anyMatch(Predicate predicate)
功能:判断是否存在至少一个元素满足条件(返回 boolean)。示例:判断是否有字符串包含 “a”:
List<String> strs = Arrays.asList("apple", "banana", "cat");
boolean hasA = strs.stream().anyMatch(s -> s.contains("a"));
System.out.println(hasA); // true(apple和banana含"a")
- allMatch(Predicate predicate)
功能:判断所有元素是否都满足条件。示例:判断所有字符串长度是否大于 2:
boolean allLong = strs.stream().allMatch(s -> s.length() > 2);
System.out.println(allLong); // true(apple(5)、banana(6)、cat(3)均满足)
- noneMatch(Predicate predicate)
功能:判断所有元素是否都不满足条件。示例:判断是否没有字符串长度小于 2:
boolean noneShort = strs.stream().noneMatch(s -> s.length() < 2);
System.out.println(noneShort); // true(所有字符串长度均≥3)
- reduce(BinaryOperator accumulator)
功能:聚合元素(如求和、求积),返回 Optional(避免空流问题)。示例:计算列表元素的和:
重载方法:带初始值的 reduce(identity, accumulator),返回具体类型(非 Optional):
int sumWithInit = nums.stream().reduce(0, (a, b) -> a + b); // 初始值0,结果10
10. min(Comparator<T> comparator) / max(Comparator<T> comparator)
功能:获取流中最小 / 最大元素(返回 Optional<T>)。示例:
// 求最小年龄
Optional minAgeUser = users.stream()
.min(Comparator.comparingInt(User::getAge));
minAgeUser.ifPresent(u -> System.out.println(u.getAge())); // 17(李四的年龄)
// 求最大年龄
Optional maxAgeUser = users.stream()
.max(Comparator.comparingInt(User::getAge));
maxAgeUser.ifPresent(u -> System.out.println(u.getAge())); // 25(王五的年龄)
总结
获取流:从集合、数组、值序列等创建流,根据需求选择串行或并行流。
中间操作:通过 filter、map、sorted 等方法链式处理数据,不立即执行。
终端操作:通过 collect、forEach、count 等触发计算,返回最终结果,流被消费
评论交流
欢迎留下你的想法