什么是流?流(Stream)是 Java 8 引入的一个强大的 API,用于处理集合数据的函数式编程操作。流提供了一种高效、声明式的方式来处理数据,特别适合对集合进行过滤、映射、排序、聚合等操作。
你可以把它想象成一条水流,它会把集合中的元素一个一个放入这条水流中,无论集合是有序的还是无序的,它们在流中都会一个一个的按照顺序被取出,你可以对取出的每一个元素做无限次数的中间处理
和一次终结操作
,终结操作后,这个流就被销毁了
- 任何的集合调用
.stream()
方法就可以得到一个流
Stream.of
String.chars
IntStream.range
拿到一个流后还可以把它转换成并发流.parallel()
Collection.parallelStream()
集合中这个方法也可以返回一个并发流
并发流可以用在一些中间操作相互独立没有依赖关系的情况下,可以提升效率,可以并行的玩完成
并发流的使用要相当小心,你要确认是否有线程安全问题,也要确认是否给你带来了性能提升
否则就忘掉它吧
- filter
过滤
- sorted
排序
- map
映射
任何返回非stream
的操作都是终结操作
- collect
收集
- Collectors.toList
- Collectors.toSet
- Collectors.toCollection
- Collectors.groupingBy
- Collectors.partitioningBy
- Collectors.joining
- Collectors.summingInt
- forEach
循环每个元素
- count/max/min
- anyMatch/noneMatch
- findFirst/findAny
用在filter操作之后,取第一个或任意取一个,返回值是一个Optional,因为filter可能没有匹配的
不要把它当成空指针用,它的正确用法是和函数式绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
public class Main {
private static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isWang() {
return name.startsWith("王");
}
}
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("张三", 20),
new User("李四", 25),
new User("王五", 23));
// 反例
Optional<User> optionalUser = users.stream().filter(User::isWang).findAny();
if (optionalUser.isPresent()) {
System.out.println(optionalUser.get().getName());
} else {
throw new IllegalStateException();
}
// 正例
User user = users.stream().filter(User::isWang).findAny().orElseThrow(IllegalStateException::new);
System.out.println(user.getName());
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Problem2 {
// 判断一段文本中是否包含关键词列表中的文本,如果包含任意一个关键词,返回true,否则返回false
// 例如,text="catcatcat,boyboyboy", keywords=["boy", "girl"],返回true
// 例如,text="I am a boy", keywords=["cat", "dog"],返回false
public static boolean containsKeyword(String text, List<String> keywords) {
return keywords.stream().anyMatch(text::contains);
}
public static void main(String[] args) {
System.out.println(containsKeyword("catcatcat,boyboyboy", Arrays.asList("boy", "girl")));
System.out.println(containsKeyword("I am a boy", Arrays.asList("cat", "dog")));
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Problem3 {
// 使用流的方法,再把之前的题目做一遍吧
// 统计一个给定的字符串中,大写英文字母(A,B,C,...,Z)出现的次数。
// 例如,给定字符串"AaBbCc1234ABC",返回6,因为该字符串中出现了6次大写英文字母ABCABC
public static int countUpperCaseLetters(String str) {
return (int) str.chars().filter(Character::isUpperCase).count();
}
public static void main(String[] args) {
System.out.println(countUpperCaseLetters("AaBbCc1234ABC"));
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public class Problem5 {
static class Order {
private Integer id;
private String name;
Order(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
// 使用流的方法,把订单处理成ID->订单的映射
// 例如,传入参数[{id=1,name='肥皂'},{id=2,name='牙刷'}]
// 返回一个映射{1->Order(1,'肥皂'),2->Order(2,'牙刷')}
public static Map<Integer, Order> toMap(List<Order> orders) {
return orders.stream().collect(Collectors.toMap((order -> order.id), (order -> order)));
}
public static void main(String[] args) {
System.out.println(toMap(Arrays.asList(new Order(1, "肥皂"), new Order(2, "牙刷"))));
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Problem6 {
// 使用流的方法,把所有长度等于1的单词挑出来,然后用逗号连接起来
// 例如,传入参数words=['a','bb','ccc','d','e']
// 返回字符串a,d,e
public static String filterThenConcat(Set<String> words) {
return words.stream().filter(ch -> ch.length() == 1).collect(Collectors.joining(","));
}
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>(Arrays.asList("a", "bb", "ccc", "d", "e"));
System.out.println(filterThenConcat(set));
}
}
|