一、Stream流
1.案例实现
按照下面的要求完成集合的创建和遍历
- 创建一个集合,存储多个字符串元素
- 把集合中所有以"张"开头的元素存储到一个新的集合
- 把"张"开头的集合中的长度为3的元素存储到一个新的集合
- 遍历上一步得到的集合
public class StreamDemo {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//把集合中所有以"张"开头的元素存储到一个新的集合
ArrayList<String> zhangList = new ArrayList<String>();
for(String s : list) {
if(s.startsWith("张")) {
zhangList.add(s);
}
}
// System.out.println(zhangList);
//把"张"开头的集合中的长度为3的元素存储到一个新的集合
ArrayList<String> threeList = new ArrayList<String>();
for(String s : zhangList) {
if(s.length() == 3) {
threeList.add(s);
}
}
// System.out.println(threeList);
//遍历上一步得到的集合
for(String s : threeList) {
System.out.println(s);
}
System.out.println("--------");
//Stream流来改进
// list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
2.Stream流的获取方法
单列集合:集合对象.stream()
双列集合:不能直接获取,需要间接获取
集合对象.keySet().stream() 和 集合对象.entrySet().stream()
数组: Arrays.stream(数组名)
同种数据类型的多个数据:Stream().of(数据1,数据2,数据3…)
3.Stream流的常见中间操作方法
Stream limit(long maxSize) | 返回此流中的元素组成的流,截取前指定参数个数的数据
Stream skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static Stream concat(Stream a, Stream b) | 合并a和b两个流为一个流
Stream distinct() | 返回由该流的不同元素(根据Object.equals(Object) )组成的流
limit&skip代码演示
public class StreamDemo02 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:取前3个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
System.out.println("--------");
//需求2:跳过3个元素,把剩下的元素在控制台输出
list.stream().skip(3).forEach(System.out::println);
System.out.println("--------");
//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);
}
}
concat&distinct代码演示
public class StreamDemo03 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4);
//需求2:跳过2个数据组成一个流
Stream<String> s2 = list.stream().skip(2);
//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
// Stream.concat(s1,s2).forEach(System.out::println);
//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
Stream.concat(s1,s2).distinct().forEach(System.out::println);
}
}
4.Stream流的常见终结操作方法
在forEach方法的底层,会循环获取到流中的每一个数据,并循环调用accept方法,并把每一个数据传递给accept方法。s就依次表示了流中的每一个时候,所以,我们只要在accept方法中,写上处理的业务逻辑就可以了。
5.Stream流的收集操作
使用Stream流的方式操作完毕之后,我想把流中的数据保存起来,该怎么办呢?
Stream流的收集方法
R collect(Collector collector)
收集到list集合或者set集合中
package com.demo3;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Test3 {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
arrayList.add(i);
}
arrayList.add(10);
arrayList.add(10);
arrayList.add(10);
List<Integer> list = arrayList.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());
System.out.println(list);
Set<Integer> set = arrayList.stream().filter(number -> number % 2 == 0).collect(Collectors.toSet());
System.out.println(set);
}
}
收集到map集合中的案例
public static Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中
package com.demo3;
import java.util.ArrayList;
import java.util.Map;
import java.util.stream.Collectors;
public class Test4 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("zhangsan,23");
arrayList.add("lisi,24");
arrayList.add("wangwu,25");
Map<String, Integer> map = arrayList.stream().filter(
(String s) -> {
String[] split = s.split(",");
int age = Integer.parseInt(split[1]);
return age >= 24;
}
).collect(Collectors.toMap(
(String s) -> {
return s.split(",")[0];
},
(String s) -> {
return Integer.parseInt(s.split(",")[1]);
}
));
System.out.println(map);
}
}
注意:collect方法只能获取到流中剩余的每一个元素,在底层不能创建容器,也不能把数据添加到容器中。
6.stream流的综合练习
- 案例需求
现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
- 男演员只要名字为3个字的前三人
- 女演员只要姓林的,并且不要第一个
- 把过滤后的男演员姓名和女演员姓名合并到一起
- 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
演员类
public class Actor {
private String name;
public Actor(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类
public class StreamTest {
public static void main(String[] args) {
//创建集合
ArrayList<String> manList = new ArrayList<String>();
manList.add("周润发");
manList.add("成龙");
manList.add("刘德华");
manList.add("吴京");
manList.add("周星驰");
manList.add("李连杰");
ArrayList<String> womanList = new ArrayList<String>();
womanList.add("林心如");
womanList.add("张曼玉");
womanList.add("林青霞");
womanList.add("柳岩");
womanList.add("林志玲");
womanList.add("王祖贤");
/*
//男演员只要名字为3个字的前三人
Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);
//女演员只要姓林的,并且不要第一个
Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
//把过滤后的男演员姓名和女演员姓名合并到一起
Stream<String> stream = Stream.concat(manStream, womanStream);
//把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
// stream.map(Actor::new).forEach(System.out::println);
stream.map(Actor::new).forEach(p -> System.out.println(p.getName()));
*/
Stream.concat(manList.stream().filter(s -> s.length() == 3).limit(3),
womanList.stream().filter(s -> s.startsWith("林")).skip(1)).map(Actor::new).
forEach(p -> System.out.println(p.getName()));
}
}