Stream
用来对集合中的数据进行各种运算和操作,例如过滤,排序,映射。。。最终得到结果
集合关注数据的存储,Stream流关注集合中存储数据的运算和操作
使用步骤
获取一个Stream流的对象
Stream<Student> stream = 1 ist. stream() ;
- 调用流对象的相关方法完成对集合中数据的中间操作(加工) filter
注意:中间操作返回的是- -个持有操作结果的一个新的流对象
Stream流对象本身不能进行任何数据的存储,只能用来对数据进行运算
中间操作会被延迟到终止操作的时候才会真正的执行
中间操作不会影响数据源
3.调用流对象的终止操作方法(对运算的结果进行最终的处理) forEach
常见的中间操作方法:
●filter(Predicate pre)参数pre描述的是过滤的条件
●sorted()用来对集合中的元素进行排序
●skip(longn) :跳过前几条
●limit(longn) :限定获取前几个元素
●distinct():用来对集合中的元素去重根据hashCode和equals方法的结果进行是否重复元素的判定
●map):映射用来提取元素的部分信息,使用时需要传入一个Function接口类型的参数
注意:map操作之后流中持有的元素的类型会发生变化
常用的终止操作:
●forEach(Consumer con):遍历最终的操作结果
●allMatch(Predicate )判断集合中元素是否全部符合某一-指定条件
代码如下:
public static void main(String[] args) {
List<Employee> list=new ArrayList<Employee>();
Stream<Employee> stream=list.stream();
list.add(new Employee("1","胡歌","男",20000,PizzaStatus.busy));
list.add(new Employee("2","刘亦菲","女",30000,PizzaStatus.free));
list.add(new Employee("3","杨幂","女",50000,PizzaStatus.busy));
list.add(new Employee("4","杨洋","男",10000,PizzaStatus.free));
list.add(new Employee("5","李易峰","男",15000,PizzaStatus.leave));
list.add(new Employee("6","毛不易","男",1500,PizzaStatus.leave));
list.add(new Employee("7","王总","男",90000,PizzaStatus.free));
//查找输出工资在6000元以上的男员工
// stream.filter(s->s.getEmpGender().equals("男") &&s.getEmpSalary()>6000).forEach(System.out::println);;
//显示工资最小的员工信息
// Optional<Employee> opt=stream.min((s1,s2 )->(int)(s1.getEmpSalary()-s2.getEmpSalary()));
// System.out.println(opt.get());
//显示最高工资
// Optional<Double> opts=stream.map(s->s.getEmpSalary()).max((a1,a2)->(int)(a1-a2));
// System.out.println(opts.get());
//统计所有员工工资的平均值
// Double collect=stream.collect(Collectors.averagingDouble(s->s.getEmpSalary()));
// System.out.println(collect);
//查找所有离职员工的员工姓名并显示
// stream.filter( s->s.getEmpStatus().equals(PizzaStatus.leave) ).map(s->s.getEmpName()).forEach(System.out::println);
//查找所有姓王的员工并收集到一个set集合里
// Set<Employee> collect=stream.filter(s->s.getEmpName().startsWith("王")).collect(Collectors.toSet());
// for (Employee e : collect) {
// System.out.println(e);
// }
//按照员工的状态信息对员工进行分组操作,并得到一个map集合
Map<PizzaStatus, List<Employee>> map=stream.collect(Collectors.groupingBy(s->s.getEmpStatus()));
for (PizzaStatus p : map.keySet()) {
System.out.println("状态:"+p);
List<Employee> emp=map.get(p);
for (Employee e : emp) {
System.out.println("\t"+e);
}
System.out.println(emp.size());
}
//遍历这个结果输出每种状态的各自人数
}
}
class Employee{
private String empld;
private String empName;
private String empGender;
private double empSalary;
private PizzaStatus empStatus;
public enum PizzaStatus{
busy,
free,
leave;
}
public String getEmpld() {
return empld;
}
public void setEmpld(String empld) {
this.empld = empld;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpGender() {
return empGender;
}
public void setEmpGender(String empGender) {
this.empGender = empGender;
}
public double getEmpSalary() {
return empSalary;
}
public void setEmpSalary(double empSalary) {
this.empSalary = empSalary;
}
public PizzaStatus getEmpStatus() {
return empStatus;
}
public void setEmpStatus(PizzaStatus empStatus) {
this.empStatus = empStatus;
}
public Employee(String empld, String empName, String empGender, double empSalary, PizzaStatus empStatus) {
super();
this.empld = empld;
this.empName = empName;
this.empGender = empGender;
this.empSalary = empSalary;
this.empStatus = empStatus;
}
@Override
public String toString() {
return "Employee [empld=" + empld + ", empName=" + empName + ", empGender=" + empGender + ", empSalary="
+ empSalary + ", empStatus=" + empStatus + "]";
}
}
网上还有一篇更详细的,我发给你们看一下,希望能帮到你们,再补充一点lambda知识
https://zhuanlan.zhihu.com/p/429885334https://zhuanlan.zhihu.com/p/429885334https://zhuanlan.zhihu.com/p/429885334那我再补充一点lambda知识吧,这个挺方便的了
Lambda表达式
Lambda 表达式的使用前提:
- 必须有接口(不能是抽象类),接口中有且仅有一个需要被重写的抽象方法。
- 必须支持上下文推导,要能够推导出来 Lambda 表达式表示的是哪个接口中的内容。
可以使用接口当做参数,然后传递 Lambda 表达式(常用),也可以将 Lambda 表达式赋值给一个接口类型的变量
Lambda的语法:
(参数列表)->{lambda体 方法体}
参数列表的类型可以省略不写
如果参数列表中只有一个参数则参数的小括号可以省略,注意:如果参数的个数为2个或以上 或者0个的时候小括号不能省略
如果lambda体中只有一条return 语句则方法体的大括号以及return 还有方法代码的分号都可以省略
特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
4大核心函数式接口,这些接口定义在java.util.function包中
- Consumer<T>:该接口中有一个抽象方法accept,特征 有一个参数无返回值void accept(T t); 消费型
- Supplier<T>:该接口中有一个抽象方法get(),特征是无参有一个返回类型 T get(); 供给型
- Function<T,S>该接口定义了一个抽象方法apply 特征是有一个参数一个返回值 R apply(T t); 函数型
- Predicate<T> 该接口中定义了一个抽象方法test 特征是有一个参数一个返回值,这个返回类型固定为boolean类型 boolean test(T t); 断言型
方法引用:Lambda的另一种表现形式
语法:对象名::实例方法名 或者 类名::静态方法名
注意:被引用的方法的参数类型和返回类型必须和接口中的抽象方法定义保持一致