目录
参考:【java基础】吐血总结Stream流操作_java stream流操作-CSDN博客、Java8 新特性实战 | JavaGuide
一、简介
Stream(流)是Java 8引入的一种全新API,用于对集合数据进行复杂操作。它提供了一种高效、简洁且函数式的方式来处理数据集合,如过滤、映射、排序和聚合等。Stream并不存储数据,而是按需计算,且支持链式操作和并行处理。
Stream流的特点:
- 非存储:Stream自身不存储元素,而是从源(集合、数组等)获取数据。
- 不可变性:Stream中的操作不会修改源数据,而是生成一个新的Stream。
- 惰性执行:Stream的中间操作是惰性的,只有在终止操作时才会执行。
- 可消费性:Stream只能被消费一次,消费后会关闭。
- 支持并行:方便地进行并行操作,充分利用多核CPU的优势。
Stream流的注意事项:
- Stream不能重复使用:一旦执行了终止操作,Stream就会被关闭。
- 避免修改源数据:在Stream操作中,不应修改源集合的内容。
- 慎用并行流:并行流在处理大量数据时有优势,但可能引入线程安全问题。
- 短路操作:某些操作如
findFirst()
、anyMatch()
等,可能在满足条件后立即结束,不需要处理所有元素。

二、创建Stream
1. 通过集合
<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
2. 通过数组
int[] nums = {1, 2, 3};
IntStream intStream = Arrays.stream(nums);
3. 通过静态方法
Stream<String> stream = Stream.of("a", "b", "c");
4. 生成无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
三、操作Stream
1. 中间操作
中间操作会返回一个新的Stream,允许多个操作链式调用。这些操作是惰性的,只有在终止操作触发时才会执行。
-
过滤(filter):根据条件过滤元素。
stream.filter(predicate)
-
映射(map):将元素映射为其他类型。
stream.map(function)
-
排序(sorted):对元素进行排序。
stream.sorted()
-
去重(distinct):去除重复元素。
stream.distinct()
2. 终止操作
终止操作会触发Stream的执行,并生成结果。
-
遍历(forEach):对每个元素执行操作。
stream.forEach(consumer)
-
聚合(reduce):将元素合并为一个结果。
stream.reduce(identity, accumulator)
-
收集(collect):将Stream转换为其他形式。
stream.collect(collector)
-
匹配(anyMatch、allMatch、noneMatch):判断元素是否满足条件。
stream.anyMatch(predicate)
-
查找(findFirst、findAny):查找元素。
stream.findFirst()
常用方法源码:
/**
* 返回一个串行流
*/
default Stream<E> stream()
/**
* 返回一个并行流
*/
default Stream<E> parallelStream()
/**
* 返回T的流
*/
public static<T> Stream<T> of(T t)
/**
* 返回其元素是指定值的顺序流。
*/
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
/**
* 过滤,返回由与给定predicate匹配的该流的元素组成的流
*/
Stream<T> filter(Predicate<? super T> predicate);
/**
* 此流的所有元素是否与提供的predicate匹配。
*/
boolean allMatch(Predicate<? super T> predicate)
/**
* 此流任意元素是否有与提供的predicate匹配。
*/
boolean anyMatch(Predicate<? super T> predicate);
/**
* 返回一个 Stream的构建器。
*/
public static<T> Builder<T> builder();
/**
* 使用 Collector对此流的元素进行归纳
*/
<R, A> R collect(Collector<? super T, A, R> collector);
/**
* 返回此流中的元素数。
*/
long count();
/**
* 返回由该流的不同元素(根据 Object.equals(Object) )组成的流。
*/
Stream<T> distinct();
/**
* 遍历
*/
void forEach(Consumer<? super T> action);
/**
* 用于获取指定数量的流,截短长度不能超过 maxSize 。
*/
Stream<T> limit(long maxSize);
/**
* 用于映射每个元素到对应的结果
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
/**
* 根据提供的 Comparator进行排序。
*/
Stream<T> sorted(Comparator<? super T> comparator);
/**
* 在丢弃流的第一个 n元素后,返回由该流的 n元素组成的流。
*/
Stream<T> skip(long n);
/**
* 返回一个包含此流的元素的数组。
*/
Object[] toArray();
/**
* 使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。
*/
<A> A[] toArray(IntFunction<A[]> generator);
/**
* 合并流
*/
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
四、使用示例
1. 过滤和遍历
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.stream()
.filter(name -> name.startsWith("C"))
.forEach(System.out::println); // 输出 "Charlie"
2. 映射和收集
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squares = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println(squares); // 输出 [1, 4, 9, 16, 25]
3. 排序
List<String> names = Arrays.asList("Bob", "Alice", "David", "Charlie");
List<String> sortedNames = names.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNames); // 输出 [Alice, Bob, Charlie, David]
4. 统计和归约
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum); // 输出 15
5. 分组
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "egg");
Map<Integer, List<String>> grouped = words.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println(grouped);
// 输出 {3=[egg], 4=[date], 5=[apple], 6=[banana, cherry]}
6.扁平化(flatMap)
用于将多个Stream合并为一个Stream。
List<List<Integer>> listOfLists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)
);
List<Integer> allNumbers = listOfLists.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(allNumbers); // 输出 [1, 2, 3, 4, 5, 6]
7.收集器(Collectors)
Collectors
类提供了多种预定义的收集策略,如toList()
、toSet()
、joining()
等。
String joined = Stream.of("A", "B", "C")
.collect(Collectors.joining(", "));
System.out.println(joined); // 输出 "A, B, C"
五、实战使用
@Test
public void test() {
List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
//返回符合条件的stream
Stream<String> stringStream = strings.stream().filter(s -> "abc".equals(s));
//计算流符合条件的流的数量
long count = stringStream.count();
//forEach遍历->打印元素
strings.stream().forEach(System.out::println);
//limit 获取到1个元素的stream
Stream<String> limit = strings.stream().limit(1);
//toArray 比如我们想看这个limitStream里面是什么,比如转换成String[],比如循环
String[] array = limit.toArray(String[]::new);
//map 对每个元素进行操作返回新流
Stream<String> map = strings.stream().map(s -> s + "22");
//sorted 排序并打印
strings.stream().sorted().forEach(System.out::println);
//Collectors collect 把abc放入容器中
List<String> collect = strings.stream().filter(string -> "abc".equals(string)).collect(Collectors.toList());
//把list转为string,各元素用,号隔开
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));
//对数组的统计,比如用
List<Integer> number = Arrays.asList(1, 2, 5, 4);
IntSummaryStatistics statistics = number.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : "+statistics.getMax());
System.out.println("列表中最小的数 : "+statistics.getMin());
System.out.println("平均数 : "+statistics.getAverage());
System.out.println("所有数之和 : "+statistics.getSum());
//concat 合并流
List<String> strings2 = Arrays.asList("xyz", "jqx");
Stream.concat(strings2.stream(),strings.stream()).count();
//注意 一个Stream只能操作一次,不能断开,否则会报错。
Stream stream = strings.stream();
//第一次使用
stream.limit(2);
//第二次使用
stream.forEach(System.out::println);
//报错 java.lang.IllegalStateException: stream has already been operated upon or closed
//但是可以这样, 连续使用
stream.limit(2).forEach(System.out::println);
}