方法总览
图片来自网络

过滤-filter
假设有如下stream流
java
record Fruit(String cname, String name, String category, String color) { }
Stream.of(
new Fruit("草莓", "Strawberry", "浆果", "红色"),
new Fruit("桑葚", "Mulberry", "浆果", "紫色"),
new Fruit("杨梅", "Waxberry", "浆果", "红色"),
new Fruit("核桃", "Walnut", "坚果", "棕色"),
new Fruit("草莓", "Peanut", "坚果", "棕色"),
new Fruit("蓝莓", "Blueberry", "浆果", "蓝色")
)
找出其中蓝色的浆果:
写法一:
java
record Fruit(String cname, String name, String category, String color) { }
Stream.of(
new Fruit("草莓", "Strawberry", "浆果", "红色"),
new Fruit("桑葚", "Mulberry", "浆果", "紫色"),
new Fruit("杨梅", "Waxberry", "浆果", "红色"),
new Fruit("核桃", "Walnut", "坚果", "棕色"),
new Fruit("草莓", "Peanut", "坚果", "棕色"),
new Fruit("蓝莓", "Blueberry", "浆果", "蓝色")
).filter(f->f.category().equals("浆果")&&f.color().equals("蓝色"))
.forEach(System.out::println);
写法二:
java
record Fruit(String cname, String name, String category, String color) {
}
Stream.of(
new Fruit("草莓", "Strawberry", "浆果", "红色"),
new Fruit("桑葚", "Mulberry", "浆果", "紫色"),
new Fruit("杨梅", "Waxberry", "浆果", "红色"),
new Fruit("核桃", "Walnut", "坚果", "棕色"),
new Fruit("草莓", "Peanut", "坚果", "棕色"),
new Fruit("蓝莓", "Blueberry", "浆果", "蓝色")
).filter(f -> f.category().equals("浆果"))
.filter(f -> f.color().equals("蓝色"))
.forEach(System.out::println);
}
映射-map
给所有的水果加上"酱"字:
java
record Fruit(String cname, String name, String category, String color) {
}
Stream.of(
new Fruit("草莓", "Strawberry", "浆果", "红色"),
new Fruit("桑葚", "Mulberry", "浆果", "紫色"),
new Fruit("杨梅", "Waxberry", "浆果", "红色"),
new Fruit("核桃", "Walnut", "坚果", "棕色"),
new Fruit("草莓", "Peanut", "坚果", "棕色"),
new Fruit("蓝莓", "Blueberry", "浆果", "蓝色")
)
.map(f->f.cname()+"酱")
.forEach(System.out::println);
}
map相当于拿到每一个数据,然后执行箭头后面操作
打印结果如下:

降维-flatmap
java
record Fruit(String cname, String name, String category, String color) {
}
Stream.of(
List.of(
new Fruit("草莓", "Strawberry", "浆果", "红色"),
new Fruit("桑葚", "Mulberry", "浆果", "紫色"),
new Fruit("杨梅", "Waxberry", "浆果", "红色"),
new Fruit("蓝莓", "Blueberry", "浆果", "蓝色")
),
List.of(
new Fruit("核桃", "Walnut", "坚果", "棕色"),
new Fruit("草莓", "Peanut", "坚果", "棕色")
)
)
.flatMap(list -> list.stream())
.forEach(System.out::println);
相当于将两个集合里面的数据提取出来,组成一个新的流。
构建流
根据已有的数组构建流:
java
Arrays.stream(array)
根据已有的 Collection 构建流(包括 List,Set 等):
java
List.of("a","b","c").stream()
把一个对象变成流:
java
Stream.of("d")
把多个对象变成流:
java
Stream.of("x", "y")
废话不多数,关于构建流,直接看代码:
java
//1.根据集合构建流
//这里的stream()是Collection接口的一个方法,所有单列集合的所有实现类都可以转换成流
//包括list,set等集合
List.of(1, 2, 3).stream().forEach(System.out::println);
//2.双列集合没有stream方法,但是我们可以将双列集合转换成单列集合,再调用stream方法
Map.of("a", 1, "b", 2)
.entrySet()//转换成键值对对象
.stream()//此时map集合是set集合的形态,可以转为流了
.forEach(System.out::println);//打印
//3.根据数组构建流
int[] array = {1, 2, 3};
Arrays.stream(array)
.forEach(System.out::println);
//4.根据对象创建流
Stream.of(1, 2, 3).forEach(System.out::println);
合并和截取
java
//1.合并
Stream<Integer> s1 = Stream.of(1, 2, 3);
Stream<Integer> s2 = Stream.of(4, 5);
Stream<Integer> concat = Stream.concat(s1, s2);
//concat.forEach(System.out::println);
//2.截取-直接给出截取位置
//skip(long n) 跳过n个数据,保留剩下的数据
//limit(long n) 保留n个数据,其他的舍弃
//concat.skip(2).forEach(System.out::println);//打印3,4,5
//concat.limit(2).forEach(System.out::println);//打印1,2
//留下中间的3,4的写法
//concat.skip(2).limit(2).forEach(System.out::println);
//3.截取-根据条件确定截取位置
//dropWhile 是 drop 流中元素,直到条件不成立,留下剩余元素
//takeWhile 是 take 流中元素,直到条件不成立,舍弃剩余元素
//concat.takeWhile(x -> x < 3).forEach(System.out::println);
//concat.dropWhile(x -> x < 3).forEach(System.out::println);
生成流
生成从 0 ~ 9 的数字(含头不含尾)
java
IntStream.range(0, 10)
或者
java
IntStream.rangeClosed(0, 9)
如果想订制,可以用 iterate 方法,例如下面生成奇数序列
java
IntStream.iterate(1, x -> x + 2)
-
参数1 是初始值
-
参数2 是一个特殊 Function,即参数类型与返回值相同,它会根据上一个元素 x 的值计算出当前元素
-
需要用 limit 限制元素个数
也可以用 iterate 的重载方法
java
IntStream.iterate(1, x -> x < 10, x -> x + 2)
iterate 的特点是根据上一个元素计算当前元素,如果不需要依赖上一个元素,可以改用 generate 方法
例如下面是生成 5 个随机 int
java
Stream.generate(()-> ThreadLocalRandom.current().nextInt()).limit(5)
不过如果只是生成随机数的话,有更简单的办法
java
ThreadLocalRandom.current().ints(5)
如果要指定上下限,例如下面是生成从 0~9 的100个随机数
java
ThreadLocalRandom.current().ints(100, 0, 10)
查找和判断

下面的代码找到流中任意(Any)一个偶数:
java
int[] array = {1, 3, 5, 4, 7, 6, 9};
Arrays.stream(array)
.filter(x -> (x & 1) == 0)
.findAny()
.ifPresent(System.out::println);
查找的案例:
java
//1.findFirst() 返回符合要求的第一个值
IntStream stream = IntStream.of(1, 2, 3, 4 5);
//System.out.println(stream.filter(x -> (x & 1) == 0).findFirst().orElse(-1));
//解释:.filter(x -> (x & 1) == 0)表示查找流里面是否有偶数
//.findFirst()表示将符合要求的数据中返回第一个元素
//.orElse(-1)表示如果没有符合要求的数据,则返回值-1
stream.filter(x -> (x & 1) == 0).findFirst().ifPresent((x) -> System.out.println(x));
//.ifPresent((x) -> System.out.println(x)表示如果存在符合的数据,则打印出来
//2.findAny找到任意一个元素即可(并行流中可以看出和findFirst的区别)
stream.filter(x -> (x & 1) == 0).findAny().ifPresent((x) -> System.out.println(x));
判断的案例:
java
//1.findFirst() 返回符合要求的第一个值
IntStream stream = IntStream.of(1, 2, 3, 4, 5);
//System.out.println(stream.anyMatch(x -> (x & 1) == 0));//true
//System.out.println(stream.allMatch(x -> (x & 1) == 0));//false
System.out.println(stream.noneMatch(x -> (x & 1) == 0));//false
去重和排序
java
//去重
//IntStream.of(1, 2, 3, 1, 2, 3, 4, 5)
// .distinct()
// .forEach(System.out::println);
//排序
record Hero(String name, int strength) {
}
Stream.of(
new Hero("独孤求败", 100),
new Hero("令狐冲", 90),
new Hero("风清扬", 98),
new Hero("东方不败", 98),
new Hero("方证", 92),
new Hero("任我行", 92),
new Hero("冲虚", 90),
new Hero("向问天", 88),
new Hero("不戒", 88)
)
.sorted((a, b) -> a.strength() < b.strength() ? -1 : a.strength() == b.strength() ? 0 : 1)
.forEach(System.out::println);
化简
reduce(init, (p,x) -> r)
-
init 代表初始值
-
(p,x) -> r
是一个 BinaryOperator,作用是根据上次化简结果 p 和当前元素 x,得到本次化简结果 r
这样两两化简,可以将流中的所有元素合并成一个结果
java
record Hero(String name, int strength) {
}
Stream.of(
new Hero("独孤求败", 100),
new Hero("令狐冲", 90),
new Hero("风清扬", 98),
new Hero("东方不败", 98),
new Hero("方证", 92),
new Hero("任我行", 92),
new Hero("冲虚", 90),
new Hero("向问天", 88),
new Hero("不戒", 88)
).reduce((h1, h2) -> h1.strength() > h2.strength() ? h1 : h2);
收集
java
collect( supplier, accumulator, combiner)
* supplier 是描述如何创建收集容器 c :`()-> c`
* accumulator 是描述如何向容器 c 添加元素 x:`(c, x) -> void`
* combiner 是描述如何合并两个容器:`(c1, c2) -> void`
* 串行流下不需要合并容器
* 并行流如果用的是并发容器,也不需要合并