Stream流(十四)


Stream流(十四)

获取Stream流

Stream流结合Lambda表达式,简化集合和数组的操作。

使用步骤

  1. 先得到一条Stream流(流水线),并把数据放上去
  2. 利用Stream流中的API进行各种操作,操作包含:数据过滤,类型转换,数据统计,数据打印等
    • 过滤和转换是中间方法,方法调用完毕后,可调用其他方法
    • 统计和打印是终结方法,最后一步,调用完毕后,不可调用其他方法

获取方式

  • 单列集合
    • 方法名:default Stream stream()
    • 说明:Collection中的默认方法
  • 双列集合
    • 不可直接获取,需通过keySet或entrySet获取单列集合后进行获取
  • 数组
    • 方法名:public static Stream stream(T[] array)
    • 说明:Arrays工具类的静态方法
  • 一堆零散数据
    • 方法名:public static Stream of(T…values)
    • 说明:Stream接口中的静态方法
    • 方法的形参是一个可变参数,可传递一堆零散的数据,也可传递数组,但传递数组必须是引用数据类型,若传递基本数据类型,会把整个数组当成一个元素放到Stream中

范例

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
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.stream.Stream;
public class Test{
public static void main(String[] args){
//单列集合
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"a","b","c","d","e");
list.stream().forEach(s->System.out.print(s+" "));
System.out.println();

//双列集合
//方式一:
HashMap<String,Integer> hm=new HashMap<>();
hm.put("a",97);
hm.put("b",98);
hm.put("c",99);
hm.put("d",100);
hm.put("e",101);
//方式一:
hm.keySet().stream().forEach(s-> System.out.print(s+"="+hm.get(s)+" "));
System.out.println();
hm.entrySet().stream().forEach(entry-> System.out.print(entry+" "));
System.out.println();

//数组
String[] arr={"a","b","c","d","e"};
Arrays.stream(arr).forEach(s-> System.out.print(s+" "));
System.out.println();
int[] arr1={1,2,3,4,5};
Arrays.stream(arr1).forEach(i-> System.out.print(i+" "));
System.out.println();

//零散数据
Stream.of(8,5,6,7,9).forEach(i -> System.out.print(i+" "));

}
}
/*
a b c d e
a=97 b=98 c=99 d=100 e=101
a=97 b=98 c=99 d=100 e=101
a b c d e
1 2 3 4 5
8 5 6 7 9
*/

中间方法

中间方法返回的新Stream流,原本的Stream流只能使用一次,建议使用链式编程。

修改Stream流中的数据,不会影响原来集合或数组中的数据。

fiter

格式

Stream filter(Predicate<? super T> predicate)

说明:过滤

limit

格式

Stream limit(long maxSize)

说明:获取前面maxSize个元素

skip

格式

Stream skip(long n)

说明:跳过前面n个元素

distinct

格式

Stream distinct()

说明:元素去重,依赖(hashCode和equals方法)

concat

格式

static Stream concat(Stream a,Stream b)

说明:合并a和b两个流为一个流

map

格式

Stream map(Function<T,R> mapper)

说明:转换流中的数据类型

范例

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class Test{
public static void main(String[] args){
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"abc","acdb","bcd","cde","aaa","dfsf","afe");
//filter方法
//只留下a开头的
System.out.println("filter方法");
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("a");
}
}).forEach(s-> System.out.print(s+" "));
System.out.println();
//lambda
list.stream().filter(s->s.startsWith("a")).forEach(s-> System.out.print(s+" "));
System.out.println();

//limit方法
//获取前3个元素
System.out.println("limit方法");
list.stream().limit(3).forEach(s-> System.out.print(s+" "));
System.out.println();

//skip方法
//跳过前3个元素
System.out.println("skip方法");
list.stream().skip(3).forEach(s-> System.out.print(s+" "));
System.out.println();

//只打印"bcd","cde","aaa"
//方法一
list.stream().limit(5).skip(2).forEach(s-> System.out.print(s+" "));
System.out.println();
//方法二
list.stream().skip(2).limit(3).forEach(s-> System.out.print(s+" "));
System.out.println();

//distinct
System.out.println("distinct方法");
ArrayList<String> list1=new ArrayList<>();
Collections.addAll(list1,"aaa","ccc","aaa");
list1.stream().distinct().forEach(s-> System.out.print(s+" "));
System.out.println();

//concat方法
System.out.println("concat方法");
Stream.concat(list.stream(),list1.stream()).forEach(s-> System.out.print(s+" "));
System.out.println();

//map方法
System.out.println("map方法");
ArrayList<String> list2=new ArrayList<>();
Collections.addAll(list2,"a-1","b-2","ab-12");
list2.stream().map(new Function<String, Integer>() {
//第一个类型:流中原本的数据类型
//第二个类型:要转换之后的类型
//apply的形参s:依次表示流里面的每一个数据
//返回值:表示转换之后的数据
//当map方法执行完毕之后,流上的数据就变成了整数,所以下面的foreach中,s依次表示流里面的每一个数据,该数据的类型为整数
@Override
public Integer apply(String s) {
String[] arr1=s.split("-");
String str=arr1[1];
return Integer.parseInt(str);
}
}).forEach(s-> System.out.print(s+" "));
System.out.println();

//lambda
list2.stream().map(s-> Integer.parseInt(s.split("-")[1])).forEach(s-> System.out.print(s+" "));
}
}
/*
filter方法
abc acdb aaa afe
abc acdb aaa afe
limit方法
abc acdb bcd
skip方法
cde aaa dfsf afe
bcd cde aaa
bcd cde aaa
distinct方法
aaa ccc
concat方法
abc acdb bcd cde aaa dfsf afe aaa ccc aaa
map方法
1 2 12
1 2 12
*/

终结方法

forEach

格式

void forEach(Consumer action)

说明:遍历

count

格式

long count()

说明:统计

toArray

格式1:

Object[] toArray()

说明:返回包含此流元素的数组。

格式2

A[] toArray(IntFunction<A[]> generator)

说明:返回指定类型的数组

collect

格式

collect(Collector collector)

说明:收集流中的数据,放到集合中

  • Collectors.toList(),可以有重复
  • Collectors.toSet(),自动去重
  • Collectors.toMap(),键不可重复,否则会报错

范例

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.stream.Collectors;

public class Test{
public static void main(String[] args){
System.out.println("forEach方法");
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"aaa","bbb","ccc");
list.stream().forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.print(s+" ");
}
});
System.out.println();
//lambda
list.stream().forEach(s-> System.out.print(s+" "));
System.out.println();

System.out.println();
System.out.println("count方法");
long num=list.stream().count();
System.out.println(num);
System.out.println();

System.out.println("toArray方法");
//InFunction的泛型,具体类型的数组
//apply的形参:流中的数据个数,要跟数组长度一致
//apply的返回值,具体类型的数组
//方法体:就是创建数组
String[] str1=list.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
System.out.println(Arrays.toString(str1));
//lambda
String[] str2=list.stream().toArray(value->new String[value]);
System.out.println(Arrays.toString(str2));
System.out.println();

System.out.println("collect方法-Collectors.toList()");
ArrayList<String> list1=new ArrayList<>();
Collections.addAll(list1,"张三-河北省-18","张三-河北省-18","李四-河南省-19","王五-湖南省-18","路人甲-湖北省-20","路人乙-河北省-19","路人丙-河北省-21");
List<String> newList=list1.stream().
filter(s->"河北省".equals(s.split("-")[1])).
collect(Collectors.toList());
System.out.println(newList);
System.out.println("collect方法-Collectors.toSet()");
Set<String> newSet=list1.stream().
filter(s->"河北省".equals(s.split("-")[1])).
collect(Collectors.toSet());
System.out.println(newSet);
System.out.println("collect方法-Collectors.toMap()");
ArrayList<String> list2=new ArrayList<>();
Collections.addAll(list2,"张三-河北省-18","李四-河南省-19","王五-湖南省-18","路人甲-湖北省-20","路人乙-河北省-19","路人丙-河北省-21");
Map<String,Integer> newMap=list2.stream().
filter(s->"河北省".equals(s.split("-")[1])).
/*
toMap: 参数一表示键的生成规则
参数二表示值的生成规则
参数一:
Function泛型一:表示流中每个数据的类型
泛型二:表示Map集合中键的数据类型

方法apply形参:依次表示流里面的每个数据
方法体:生成键的代码
返回值:已经生成的键
参数二:
Function泛型一:表示流中每个数据的类型
泛型二:表示Map集合中值的数据类型

方法apply形参:依次表示流里面的每个数据
方法体:生成值的代码
返回值:已经生成的值
*/
collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
},
new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[2]);
}}));
System.out.println(newMap);
//lambda
Map<String,Integer> newMap1=list2.stream().
filter(s->"河北省".equals(s.split("-")[1])).
collect(Collectors.toMap(s-> s.split("-")[0],
s->Integer.parseInt(s.split("-")[2])));
System.out.println(newMap1);
}
}
/*
forEach方法
aaa bbb ccc
aaa bbb ccc

count方法
3

toArray方法
[aaa, bbb, ccc]
[aaa, bbb, ccc]

collect方法-Collectors.toList()
[张三-河北省-18, 张三-河北省-18, 路人乙-河北省-19, 路人丙-河北省-21]
collect方法-Collectors.toSet()
[路人丙-河北省-21, 张三-河北省-18, 路人乙-河北省-19]
collect方法-Collectors.toMap()
{路人丙=21, 路人乙=19, 张三=18}
{路人丙=21, 路人乙=19, 张三=18}

*/

范例

例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
过滤奇数,只剩下偶数
并将结果保存起来
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Test{
public static void main(String[] args){
ArrayList<Integer> list=new ArrayList<>();
Collections.addAll(list,1,2,3,4,5,6,7,8,9,10);
List<Integer> newList = list.stream().filter(i->i%2==0).collect(Collectors.toList());
System.out.println(newList);
}
}
/*
[2, 4, 6, 8, 10]
*/

例2

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
/*
练习:
创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄
"zhangsan,23"
"lisi,24"
"wangwu,25"
保留年龄大于等于24的人,并将结果放入Map集合中,姓名为键,年龄为值
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;

public class Test{
public static void main(String[] args){
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"zhangsan,23","lisi,24","wangwu,25");
Map<String,Integer> map=list.stream().
filter(s->Integer.parseInt(s.split(",")[1])>=24).
collect(Collectors.toMap(s-> s.split(",")[0],
s->Integer.parseInt(s.split(",")[1])));
System.out.println(map);
}
}
/*
{lisi=24, wangwu=25}
*/

例3

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
/*
现有两个ArrayList集合,分别存储6名男演员的名字和年龄以及6名女演员的名字和年龄,
姓名和年龄中间用逗号隔开,
比如:张三,23
要求完成以下操作:
1.男演员只要名字为3个字的前两个人
2.女演员只要姓杨的,并且不要第一个
3.把过滤后男演员信息和女演员信息合并到一起
4.将上一步的演员信息转换成Actor对象
5.将所有的演员对象都保存到List集合中
演员类Actor,属性名:name,age
男演员:"张楚阳,24","叶沙比,23","刘不甜,22","吴签,24","谷甲,30","肖凉凉,27"
女演员:"蔡徐坤,24","杨以,36","高媛媛,43","张甜甜,31","刘失,35","杨扎进,33"
*/
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Test{
public static void main(String[] args){
ArrayList<String> boyList=new ArrayList<>();
ArrayList<String> girlList=new ArrayList<>();
Collections.addAll(boyList,"张楚阳,24","叶沙比,23","刘不甜,22","吴签,24","谷甲,30","肖凉凉,27");
Collections.addAll(girlList,"蔡徐坤,24","杨以,36","高媛媛,43","张甜甜,31","刘失,35","杨扎进,33");
Stream<String> boyStream=boyList.stream().
filter(s->s.split(",")[0].length()==3).
limit(2);
Stream<String> girlStream=girlList.stream().
filter(s->s.startsWith("杨")).
skip(1);
List<Actor> list=Stream.concat(boyStream,girlStream).
map(s->new Actor(s.split(",")[0],Integer.parseInt(s.split(",")[1]))).
collect(Collectors.toList());
System.out.println(list);
}
}
/*
[Actor{name = 张楚阳, age = 24}, Actor{name = 叶沙比, age = 23}, Actor{name = 杨扎进, age = 33}]
*/

Author: ljs
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source ljs !
评论
  TOC