什么是Stream流?
- 在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream流概念。
- 目的:用于简化集合和数组操作的API。
体验Stream流的作用
- 创建一个集合,存储多个字符串元素。
- 把集合中所有以"张"开头的元素存储到一个新的集合。
- 把"张"开头的集合中的长度为3的元素存储到一个新的集合。
- 遍历上一步得到的集合中的元素输出。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
Collections.addAll(names, "张三丰", "张无忌", "周芷若", "赵敏", "张强");
System.out.println(names);
//1、从集合中找出姓张的放到新集合
// List<String> zhangList = new ArrayList<>();
// for (String name : names) {
// if (name.startsWith("张")) {
// zhangList.add(name);
// }
// }
// //2、找名称长度是3的姓名
// List<String> zhangThreeList = new ArrayList<>();
// for (String name : zhangList) {
// if (name.length() == 3) {
// zhangThreeList.add(name);
// }
// System.out.println(zhangThreeList);//[张三丰, 张无忌]
// }
//3、使用stream实现,仅需一行代码
names.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s->System.out.println(s));
/*
张三丰
张无忌
*/
}
}
Stream流式思想的核心:
1.先得到集合或者数组的Stream流(就是一根传送带)
2.把元素放上去
3.然后就用这个Stream流简化的API来方便的操作元素。
Stream流的三类方法
- 获取Stream流
-
- 创建一条流水线,并把数据放到流水线上准备进行操作。
- 中间方法
-
- 流水线上的操作。一次操作完毕之后,还可以继续进行其他操作,支持链式编程。
- 终结方法
-
- 一个Stream流只能有一个终结方法,是流水线上的最后一个操作。
集合获取Stream流的方式
- 可以使用Collection接口中的默认方法stream()生成流
方法名称 | 说明 |
default Stream<E> stream() | 获取当前集合对象的Stream流 |
数组获取Stream流的方式
方法名称 | 说明 |
public static <T> Stream<T> stream(T[ ] array) | 获取当前数组的Stream流 |
public static<T> Stream<T> of(T... values) | 获取当前数组/可变数据的Stream流 |
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo2 {
public static void main(String[] args) {
//-------------Collecting集合获取流-------------
Collection<String> list = new ArrayList<>();
Stream<String> s = list.stream();
//-------------Map集合获取流----------------
Map<String, Integer> maps = new HashMap<>();
//键流
Stream<String> keyStream = maps.keySet().stream();
//值流
Stream<Integer> valueStream = maps.values().stream();
//键值对流(拿整体)
Stream<Map.Entry<String, Integer>> keyAndValueStream = maps.entrySet().stream();
//-----------------数组获取流----------------
String[] names = {"赵敏","周芷若"};
Stream<String> nameStream = Arrays.stream(names);
Stream<String> nameStream2 = Stream.of(names);
}
}
Stream流的常用API(中间操作方法)
方法名称 | 说明 |
Stream<T> filter(Predicate<? super T> predicate) | 用于对流中的数据进行过滤。 |
Stream<T> limit( long maxSize) | 获取前几个元素 |
Stream<T> skip( long n) | 跳过前几个元素 |
Stream<T> distinct() | 去除流中重复的元系。依赖hashcode和equals方法 |
static <T> Stream<T> concat(Stream a,Stream b) | 合并a和b两个流为一个流 |
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class StreamDemo3 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
list.add("张三丰");
// list.stream().filter(new Predicate<String>() {
// @Override
// public boolean test(String s) {
// return s.startsWith("张");
// }
// });
//Lambda表达式化简
list.stream().filter( s-> s.startsWith("张")).forEach(s-> System.out.println(s));
/*
张无忌
张强
张三丰
张三丰
*/
long size = list.stream().filter(s -> s.length() == 3).count();
System.out.println(size);//4
list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(s -> System.out.println(s));
//简化
list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(System.out::println);
/*
张无忌
张强
*/
list.stream().filter(s -> s.startsWith("张")).skip(2).forEach(s -> System.out.println(s));
/*
张三丰
张三丰
*/
//Map加工方法
//给集合元素的前面都加上一个:可爱的
list.stream().map(s -> "可爱的:"+s).forEach(s -> System.out.println(s));
//把所有的名称都加工成学生对象
list.stream().map(s -> new Student(s)).forEach(s -> System.out.println(s));
//简化
// list.stream().map(Student::new).forEach(System.out::println); //构造器引用 方法引用
//合并流
Stream<String> s1 = list.stream().filter(s->s.startsWith("张"));
Stream<String> s2 = Stream.of("Java1","Java2");
Stream<String> s3 = Stream.concat(s1, s2);
//去重
s3.distinct().forEach(s -> System.out.println(s));
}
}
注意:
- 中间方法也称为非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程。
- 在Stream流中无法直接修改集合、数组中的数据。
Stream流的常见终结操作方法
方法名称 | 说明 |
void forEach(Consumer action) | 对此流的每个元素执行遍历操作 |
long count() | 返回此流中的元素数 |
Stream流的收集操作
收集Stream流的含义:就是把Stream流操作后的结果数据转回到集合或者数组中去。
Stream流的收集方法
方法名称 | 说明 |
R collect(Collector collector) | 开始收集Stream流,指定收集器 |
Collectors工具类提供了具体的收集方式
方法名称 | 说明 |
public static <T> Collector toList() | 把元素收集到List集合中 |
public static <T> Collector toSet() | 把元素收集到Set集合中 |
public static Collector toMap(Function keyMapper , Function valueMapper) | 把元素收集到Map集合中 |
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamDemo4 {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
Collections.addAll(names, "张三丰", "张无忌", "周芷若", "赵敏", "张强","张三丰");
Stream<String> s = names.stream().filter(s1 -> s1.startsWith("张"));
List<String> list = s.collect(Collectors.toList());
System.out.println(list);//[张三丰, 张无忌, 张强, 张三丰]
//注意:流只能使用一次
Stream<String> s2 = names.stream().filter(s1 -> s1.startsWith("张"));
Set<String> set = s2.collect(Collectors.toSet());
System.out.println(set);//[张强, 张三丰, 张无忌]
Stream<String> s3 = names.stream().filter(s1 -> s1.startsWith("张"));
Object[] arrays = s3.toArray();
System.out.println("Arrays数组内容:" + Arrays.toString(arrays)); //Arrays数组内容:[张三丰, 张无忌, 张强, 张三丰]
}
}