Stream流
2026/1/4大约 5 分钟
Stream流
Stream流是Java 8引入的一种新的集合操作方式,它提供了一种高效且易于使用的方式来处理集合数据。
以后用for循环处理数据的都可以用streamAPI实现。
不可变集合
不可变集合(Immutable Collections)是Java 9引入的一种新的集合类型.
通过of静态方法创建,只读。
List<String> immutableList = List.of("a", "b", "c");
Set<String> immutableSet = Set.of("a", "b", "c");
Map<String, Integer> immutableMap = Map.of("a", 1, "b", 2, "c", 3);
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("李四","北京");
hashMap.put("张三","河南");
//获取所有键值对对象。
Set<Map.Entry<String, String>> entries = hashMap.entrySet();
//把键值对对象变为数组
//toArray方法在底层会比较集合的长度跟数组的长度两者的大小
//如果集合的长度>数组的长度:数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
//如果集合的长度<=数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用
Map.Entry[] array = entries.toArray(new Map.Entry[0]);
Map.ofEntries(array); // 可以传入Map.Entry[]数组无上限
// 可以简化为
Map map = Map.ofEntries(hashMap.entrySet().toArray(new Map.Entry[0]));
//其实直接copyOf方法就可以了,JDK10后才可以
Map.copyOf(hashMap);map里面的of方法参数有上限,最多10个键值对。
Java 的数组创建语法和数组访问语法长得太像了
new Map.Entry[0] 并不是 在访问下标为 0 的元素。
访问元素(Access): array[0] -> 意思是“给我这个数组里的第 0 个元素”。
创建数组(Creation): new Type[0] -> 意思是“给我创建一个长度为 0 的新数组”。
所以,new Map.Entry[0] 的真实含义是: “请 JVM 给我在堆内存里 new 出来一个数组,这个数组专门用来放 Map.Entry 对象,而且它的长度是 0.”
Stream流
使用方法:
首先获取流,然后执行中间方法和结束方法。
获取流

public class StreamDemo {
public static void main(String[] args) {
//Collection体系的集合可以使用默认方法stream()生成流
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();
//Map体系的集合间接的生成流
Map<String,Integer> map = new HashMap<String, Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
//数组可以通过Arrays中的静态方法stream生成流,不论是int[],float[],double[]还是String[]
String[] strArray = {"hello","world","java"};
Stream<String> strArrayStream = Arrays.stream(strArray);
//同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);
//注意:
//Stream接口中静态方法of的细节
//方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组
//但是数组必须是引用数据类型的,如果传递基本数据类型,是会把整个数组当做一个元素,放到Stream当中。
Stream.of(arr1).forEach(s-> System.out.println(s));//[I@41629346
}
}中间方法

提示
注意1: 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
注意2: 修改Stream流中的数据,不会影响原来集合或者数组中的数据
ArrayList<String> list1 = new ArrayList<>();
Collections.addAll(list1,"张三丰","张无忌","李逵","李鬼","张翠山","马化腾","马云","马泽林");
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list1,"腾讯","华为","阿里");
//filter
list1.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s)); //张三丰 张无忌 张翠山
//limit
list1.stream().limit(3).forEach(s -> System.out.println(s)); //张三丰 张无忌 李逵
//skip
list1.stream().skip(5).forEach(s -> System.out.println(s)); // 马化腾 马云 马泽林
//distinct
list1.stream().distinct();
//concat
Stream<String> stream1 = list1.stream();
Stream<String> stream2 = list2.stream();
Stream<String> stringStream = Stream.concat(stream1, stream2);
ArrayList<String> list3 = new ArrayList<>();
Collections.addAll(list1,"字节-0","腾讯-1","华为-1","阿里-1");
//map
list1.stream().map(s->Integer.parseInt(s.split("-")[1]));终结方法

//forEach
list.stream().forEach(s -> System.out.println(s));
//count
list.stream().count();
// toArray
//toArray方法在底层会比较集合的长度跟数组的长度两者的大小
//如果集合的长度>数组的长度:数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
//如果集合的长度<=数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用
//toArray 方法的这个参数是一个生成器(IntFunction),value是流的大小,new XXX[value]是生成器返回的数组的类型。
list.stream().toArray( value -> new String[value]);
//collect:tolist()
list.stream().collect(Collectors.toList());
//collect:toSet()
list.stream().collect(Collectors.toSet());
//collect:toMap()
//toMap : 参数一表示键的生成规则
// 参数二表示值的生成规则
/*
* 参数一:
* Function泛型一:表示流中每一个数据的类型
* 泛型二:表示Map集合中键的数据类型
*
* 方法apply形参:依次表示流里面的每一个数据
* 方法体:生成键的代码
* 返回值:已经生成的键
*
* 参数二:
* Function泛型一:表示流中每一个数据的类型
* 泛型二:表示Map集合中值的数据类型
*
* 方法apply形参:依次表示流里面的每一个数据
* 方法体:生成值的代码
* 返回值:已经生成的值
*/
list.stream().collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
//例如数据: 张无忌-男-15
return s.split("-")[0];
}
}, new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[2]);
}
}));
//Lambda表达式简化
list.stream().collect(Collectors.toMap(
s -> s.split("-")[0],
s -> Integer.parseInt(s.split("-")[2])
));