Stream 流
看之前:需要一些Lambda语法知识,可以查看参考资料中的文章:万字详解,JDK1.8的Lambda、Stream和日期的使用详解。
正文
Java8 API Stream 允许你以声明性方式处理数据集合或数组(通过查询语句来表达。
Stream 的特点:
- Stream 自己不会存储数据
- Stream 不会改变源对象,他们会返回一个持有结果的新对象
- Stream 操作是延迟执行的,意味着他们只会在需要结果的时候才会执行。
- Stream 只能消费一次,消费完毕之后就会关闭。
Stream流的使用分三步:创建流、中间操作、终端操作;Stream流是延迟执行的,只有终端操作才能触发整个流的执行。
1、流的操作步骤
流的操作:
- 创建流:新建一个流
- 中间操作:在一个或者多个步骤中将初始 stream 转化为另一个 stream
- 终端操作:使用一个终端操生成一个结果,该操作会强制它之前的延迟操作立即执行,在这之后 stream 就无法再次使用了。
1.1 创建流
1.2 中间操作:
中间操作会返回另一个流,多个中间操作可以连接起来可以形成一个查询。重要的是,除非流水线上触发一个终端操作,否则中间操作不会执行任何处理。
操作 | 返回类型 | 操作参数 | 作用 |
---|---|---|---|
filter | Stream | Predicate | 过滤符合条件的元素 |
map | Stream | Function<T,R> | 将元素映射成另一个元素 |
limit | Stream | int | 截断流 |
skip | Stream | int | 跳过 |
distinct | Stream | 无 | 去重 |
sorted | Stream | Compartor | 排序 |
1.3 终端操作:
终端口操作会从流的流水线生成结果。其结果是任何不是流的值,比如List、 Integer,甚至void。
操作 | 返回类型 | 操作参数 | 作用 |
---|---|---|---|
foreach | void | Comsumer | 对流中的每个元素执行操作 |
min | Optional | Comparator | 取最小元素 |
max | Optional | Comparator | 取最大值 |
count | long | 无 | 计数 |
reduce | T | BinaryOperator | 规约 |
collect | Collector | 收集 |
默认收集器Collectors,Collectors是一个工具类,是JDK预实现Collector的工具类,
它内部提供了多种Collector用来帮我们生成结果集合
工厂方法 | 返回类型 | 作用 |
---|---|---|
toList | List | 把流中所有项目收集到List |
toSet | Set | 把流中所有项目收集到Set,去除重复数据 |
toCollection | Collection | 把流中的所有项目收集到给定的供应源创建的集合 |
toMap | Map<K,U> | 把流中的键和值放入Map中,如果有相同的元素,会抛出IllegalStateException异常。 |
counting | Long | 计算流中元素个数 |
summingInt | Integer | 对流中项目的一个整数属性求和 |
groupingBy | Map<K, List> | 根据项目中的某个属性值,对流中元素做分组,并将该属性值做map的key |
partitionBy | Map<Boolean, List> | 根据项目中的表达式结果true或者false做区分 |
2、Stream 的使用代码示例
学生类:
public class StudentBO {
/** 学生id **/
Integer id;
/** 学生姓名 **/
String name;
/** 班级id **/
Integer classId;
/** 学生年龄 **/
Integer age;
/** 分数 **/
Integer score;
/**身高 cm **/
Integer height;
/** 体重 kg**/
Integer weight;
/**
* 获取学生的身体质量指数
* @return
*/
public Double getStudentBMI() {
return (weight * 10000.0 / (height * height));
}
/**
* 根据id大小对学生进行比较
* @param s1
* @param s2
* @return
*/
public static int compare(StudentBO s1, StudentBO s2) {
return (s1.getId().compareTo(s2.id));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StudentBO studentBO = (StudentBO) o;
return Objects.equals(id, studentBO.id);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age, score);
}
//省略属性的get和set方法
}
先预加载需要操作的集合:
public class StreamDemoTest {
private List<StudentBO> studentBOList = new ArrayList();
@Before
public void initTest() {
StudentBO studentA = new StudentBO();
StudentBO studentB = new StudentBO();
StudentBO studentC = new StudentBO();
StudentBO studentD = new StudentBO();
studentA.setId(1);
studentA.setAge(20);
studentA.setName("Tom");
studentA.setScore(100);
studentA.setHeight(175);
studentA.setWeight(60);
studentB.setId(2);
studentB.setAge(19);
studentB.setName("Ken");
studentB.setScore(60);
studentB.setHeight(180);
studentB.setWeight(60);
studentC.setId(3);
studentC.setAge(19);
studentC.setName("Bob");
studentC.setScore(70);
studentC.setHeight(175);
studentC.setWeight(80);
studentBOList.add