1、Stream流状态划分
Stream流操作分为
终结操作
和中间操作
。终结操作
又分为短路操作
和非短路操作
,中间操作
又分为无状态
和有状态
操作。
中间操作
:会返回一个新的流,一个流可以后面跟随零个或多个中间操作。终结操作
:返回最终的结果。一个流只能有一个终结操作,当这个操作执行后,这个流就被使用“光”了,无法再被操作。短路操作
:遇到某些符合条件的元素就可以得到最终结果。非短路操作
:必须处理完所有元素才能得到最终结果。无状态操作
: 无状态是指元素的处理不受之前元素的影响。有状态操作
: 有状态是指该操作只有拿到所有元素之后才能继续下去。
2、开发中常用方法
下面已一个包含Person对象的列表为例。
//定义Person对象
public class Person {
private Integer id;
private String name;
private String sex;
private Integer age;
public Person(Integer id, String name, String sex, Integer age) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
//定义列表
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person(1,"张三","男",38));
personList.add(new Person(2,"小小","女",2));
personList.add(new Person(3,"李四","男",65));
personList.add(new Person(4,"王五","女",20));
personList.add(new Person(5,"赵六","男",38));
personList.add(new Person(6,"大大","男",65));
//下述流操作
...
}
1.map
转换流(中间操作|无状态):将一种流转换成另外一种流。
//1.取出该集合中的所有姓名组成一个新集合
List<String> nameList = personList.stream().map(person -> person.getName()).collect(Collectors.toList());
2.collect
聚合操作,封装目标数据。
//2.list转map,K为id,V为Person对象
Map<Integer, Person> personMap = personList.stream().collect(Collectors.toMap(person -> person.getId(), person -> person));
//3、进行map集合存放,key为age值 value为Person对象 它会把相同age的对象放到一个集合中
Map<Integer, List<Person>> ageMap = personList.stream().collect(Collectors.groupingBy(person -> person.getAge()));
3.min\max\sum
//4、获取最小年龄最大年龄
int minAge = personList.stream().mapToInt(person -> person.getAge()).min().getAsInt();
int maxAge = personList.stream().mapToInt(person -> person.getAge()).max().getAsInt();
//5.集合属性求和
int sum = personList.stream().mapToInt(person -> person.getAge()).sum();
4、filter
过滤流(中间操作|无状态):过滤流中的元素,返回一个符合条件的Stream。
//1、查找年龄大于20岁的人数
long count = personList.stream().filter(person -> person.getAge() > 20).count();
//2、查找年龄大于20岁,性别为男的人数
long count1 = personList.stream().filter(person -> person.getAge() > 20).filter(person -> "男".equals(person.getSex())).count();
3、Stream并行计算
Stream可以对一个聚合对象按照某种计算规则进行并行计算,加快计算效率,底层采用fork-join实现,以下代码实现返回一组数据相加的结果。
1、不采用并行计算
public static void main(String[] args) {
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
//.parallel()
.reduce((a, b) -> {
System.out.println(String.format("%s: %d + %d = %d", Thread.currentThread().getName(), a, b, a + b));
return a + b;
}).ifPresent(System.out::println);
}
2、采用并行计算
public static void main(String[] args) {
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
.parallel()
.reduce((a, b) -> {
System.out.println(String.format("%s: %d + %d = %d", Thread.currentThread().getName(), a, b, a + b));
return a + b;
}).ifPresent(System.out::println);
}
可见parallel()开启并行计算的方法、开启后会使用多个线程进行计算,将计算过程分解成一个个子任务,本质上是一种fork-join的实现方法。
reduce():reduce 操作可以实现从Stream中生成一个值,其生成的值不是随意的,而是根据指定的计算模型。比如,之前提到count、min和max方法,因为常用而被纳入标准库中。事实上,这些方法都是reduce操作。
ifPresent:前面操作结果不为空则对其执行对应方法。