Stream流🍟
1. Stream流
1.1 体验Stream流
需求:
1. 创建一个集合,存储多个字符串元素 2. 把集合中所有以“张”为开头的元素存储到一个新集合中 3. 把“张”开头的集合中的长度为3的元素存储到一个新的集合中 4. 遍历上一步得到的集合
使用Stream流的方式完成过滤操作:
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() >= 3).forEach(System.out::println);
- 生成流→过滤姓张→过滤长度为3→逐一打印
- Stream流把真正的函数式编程风格引入到Java中
1.2 Stream流的生成方式
Stream流的使用
- 生成流
- 通过数据源(集合、数组等)生成流
- list.stream
- 中间操作
- 一个六可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用
- filter()
- 终结操作
- 一个流只能有一个终结操作,当这个操作执行后,流就被用"光"了,无法再被操作。所以这必定是流的最后一个操作
- forEach()
Stream流的常见生成方式:
-
Collection体系的集合可以使用默认方法stream()生成流
- default Stream stream()
-
Map体系的集合间接的生成流
-
数组可以通过Stream接口的静态方法of(T… values)生成流
1.3 Stream流常见的中间操作方法
Stream流常见的中间操作方法:
-
Stream filter(Predicate predicate):用于对流中的数据进行过滤
- boolean test(T t):给定的参数进行判断,返回一个boolean值
-
Stream limit(long maxSize):返回此流中的元素组成的流,截取前指定参数个数的数据 (返回前几个)
-
Stream skip(long n):跳过指定参数个数的数据,返回由该流的剩余参数的组成元素 (返回后几个)
-
static Stream concat(Stream a, Stream b):合并a和b两个流为一个流
-
Stream distinct():返回由该流的不同元素(根据Object.equals(Object))组成的流
-
Stream sorted():返回由此流的元素组成的流,根据自然顺序排序
-
Stream sorted(Comparator comparator):返回由此流的元素组成的流,根据提供的Comparator进行排序
-
Stream map(Function mapper):返回由给定函数应用于此流的元素的结果组成的流
- Function接口中的方法 R apply(T t)
-
IntStream mapToInt(ToIntFunction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素结果
- IntStream:表示原始的int流
- ToInFunction接口中的方法 int applyAsInt(T value)
1.4 Stream流的常见终结操作方法
- void forEach(Consumer action):对此流的每一个元素执行操作
- Consumer接口中的方法 void accept(T t):对给定的参数执行操作
- long count():返回此流中的元素数
1.5 Stream流的练习
现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下操作
- 男演员只要名字为3个字的前三人
- 女演员只要姓林的,并且不要第一个
- 把过滤后的男演员姓名和女演员姓名合并到一起
- 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
- 演员类Actor已经提供,里面有一个成员变量,有一个带参构造方法,以及成员变量对应的getter、setter方法
public class StreamDemo01 {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("王劲松");
list1.add("秦昊");
list1.add("陈宝国");
list1.add("廖凡");
list1.add("张志坚");
list1.add("陈建斌");
ArrayList<String> list2 = new ArrayList<>();
list2.add("杨幂");
list2.add("刘诗诗");
list2.add("林志玲");
list2.add("刘亦菲");
list2.add("林心如");
list2.add("林青霞");
// 男演员只要名字为3个字的前三人
Stream<String> stream1 = list1.stream().filter(s -> s.length() == 3).limit(3);
// 女演员只要姓林的,并且不要第一个
Stream<String> stream2 = list2.stream().filter(s -> s.startsWith("林")).skip(1);
// 把过滤后的男演员姓名和女演员姓名合并到一起
Stream<String> stream = Stream.concat(stream1, stream2);
// 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
// stream.map(Actor::new).forEach(System.out::println);
stream.map(Actor::new).forEach(actor -> System.out.println(actor.getName()));
}
}
1.6 Stream流的收集操作
对数据使用Stream流的方式操作完毕后,我想把流中的数据收集到集合中,该怎么办呢?
Stream流的收集方法
- R collect(Collector collector)
- 但是这个收集方法的参数是一个接口Conllector接口
工具类Collectors提供了具体的收集方式
- public static Collector toList():把元素收集到List集合中
- public static Collector toSet():把元素收集到Set集合中
- public static Collector toMap(Function keyMapper, Function valueMapper):把元素收集到Map集合中
public class StreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
// 1. 得到名字为3个字的流
Stream<String> stream1 = list.stream().filter(s -> s.length() == 3);
// 2. 把使用Stream流操作完毕的数据收集到List结合中遍历
List<String> nameList = stream1.collect(Collectors.toList());
for (String s : nameList) {
System.out.println(s);
}
System.out.println("======================");
Set<Integer> set = new HashSet<>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
set.add(35);
// 得到年两大于25的流
Stream<Integer> stream2 = set.stream().filter(age -> age > 25);
// 把使用Stream流操作完毕的数据收集到set集合中
Set<Integer> ageSet = stream2.collect(Collectors.toSet());
for (Integer age : ageSet) {
System.out.println(age);
}
System.out.println("======================");
// 定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组成
String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};
// 得到字符串中年龄数据大于28的流
Stream<String> stringStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
// 把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中姓名作为键,年龄作为值
Map<String, Integer> map = stringStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}