java8Stream API提供了大量的集合操作支持,大致分为filter、map、reduce,在这三个大的阶段又会有许多的细分,具体看个人操作需求。操作的案例对象如下:
class Student{
String name;
Integer age;
char gender;
LocalDate birth;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public LocalDate getBirth() {
return birth;
}
public void setBirth(LocalDate birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
", birth=" + birth +
'}';
}
public static void main(String[] args) {
Student stu1=new Student();
stu1.setName("张三");
stu1.setAge(20);
stu1.setGender('男');
stu1.setBirth(LocalDate.parse("1998-02-06"));
Student stu2=new Student();
stu2.setName("张三");
stu2.setAge(24);
stu2.setGender('男');
stu2.setBirth(LocalDate.parse("1998-04-05"));
Student stu3=new Student();
stu3.setName("张三");
stu3.setAge(22);
stu3.setGender('女');
stu3.setBirth(LocalDate.parse("2001-02-06"));
List<Student> stus=new ArrayList<>();
stus.add(stu1);
stus.add(stu2);
stus.add(stu3);
}
//按照年龄进行排序,不熟悉前这样写
stus.stream().sorted(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge().compareTo(o2.getAge());
}
}).forEach(System.out::println);
//熟悉后这样写
stus.stream().sorted((o1,o2)-> o1.getAge().compareTo(o2.getAge()))
.forEach(System.out::println);
实质是如果你集合中的对象元素实现了Comparator接口则直接会根据其进行排序,不必再在函数时传递参数时进行比较的实现,基本int类型没有compareTo()方法也可以编写为o1.getAge()-o2.getAge()这种,总之实质是自己编写内部实现规则。
//过滤掉出生年月在2000-01-01年之后的,不熟悉前
stus.stream().filter(new Predicate<Student>() {
@Override
public boolean test(Student student) {
LocalDate condition = LocalDate.parse("2000-01-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return student.getBirth().isAfter(condition);
}
}).forEach(System.out::println);
//熟悉后
stus.stream().filter((student)->{
LocalDate condition = LocalDate.parse("2000-01-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return student.getBirth().isAfter(condition);
}).forEach(System.out::println);
Java8的关于Date的API提供了判断日期前后比较的function,拿来用即可,也是很方便的,实质Predicate要求实现的是test方法,false则顾虑掉,true则放行到下一步操作。和配置java web的filter简直超级像。
//统计三者年龄之和,不熟悉之前
Integer count = stus.stream().map(student -> student.getAge()).reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return integer + integer2;
}
}).get();
//熟悉之后
Integer count = stus.stream().map(student -> student.getAge()).
reduce((integer ,integer2)-> integer + integer2)
.get();
//集合分组,参数一分组条件,参数2默认重载一个list
Map<Character, List<Student>> collect1 = stus.stream().collect(Collectors.groupingBy(
student -> student.getGender()));
System.out.println("collect1 = " + collect1);
//集合分组,参数一分组条件,参数2分组后将元素的值转化为你想要的mappping映射
Map<Character, Set<Student>> collect = stus.stream().collect(Collectors.groupingBy(
student -> student.getGender(),
Collectors.mapping(student -> student, Collectors.toSet())));
stus.stream().skip(2).limit(2)
.forEach(System.out::println) ;
skip是跳过的记录数,limit理解为页数据的大小,如上意为跳过两条数据,集合保存3,4条数据
Stream API非常好用且大数据量也是性能高效的操作,使用时需注意的是
1.由于Stream 是懒加载操作,因此需要小心没有如get(),collect()等action方法操作时,突然发现stream“没有执行”这种误区。非常类似大数据hadoop,spark中的action算子等描述了。
2.Stream 在进行了action操作之后会关闭流,因此还要进行操作的话需要重新调用stream()打开新流