第十二章 Lambda
12.1 函数式接口
- 只有一个必须被重写的抽象方法的接口
- @FunctionalInterface 注解强制检测是否为函数式接口
- java.util.function 包下提供了一系列的函数式接口
- 方法的形参:函数式接口
- 方法的实参:lambda表达式
四大内置函数式接口 :
Consumer 消费型接口
void accept(T t) 对给定的参数执行此操作
Function<T,R> 函数型接口
R apply(T t) 将此函数应用于给定的参数。
Supplier 供给型接口
T get() 获取结果
Predicate 段言型接口
boolean test(T t) 根据给定的参数计算此谓词
package Thursday;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class TestConsumer {
public static void main(String[] args) {
consumer(10000,money-> System.out.println("今日消费"+money));
System.out.println(function("wang",str->str.toUpperCase()));
System.out.println(supplier(5,()-> (int)(Math.random() * ((10 - 5) + 1)) + 5));
System.out.println(predicate(List.of("汪超","常坤","赵士祥"),l->l.length()>=2));
}
// 消费型接口
public static void consumer(int money, Consumer<Integer> sc){
sc.accept(money);
}
//函数型接口
public static String function(String str, Function<String,String> fc){
return fc.apply(str);
}
// 供给型接口
public static List<Integer> supplier(int num, Supplier<Integer> pc){
List<Integer> li=new ArrayList<>();
for (int i=1;i<=num;i++){
li.add(pc.get());
}
return li;
}
// 断言型接口
public static List<String> predicate(List<String> li,Predicate<String> pd){
List<String> list =new ArrayList<>();
for (String s:li){
if (pd.test(s)){
list.add(s);
}
}
return list;
}
}
12.2 方法引用
方法引用 :: (看得懂,能修改)
-
**作用:**简化lambda表达式的,是lambda表达式的另外一种变现形式
-
**前提 :**当lambda体的实现是通过调用另外一个方法实现的,可以通过方法引用直接引用这个方法,用来简化
完整的lambda表达式的结构
-
语法:
- 对象 :: 实例方法
- 类名 :: 静态方法
- 类名 :: 实例方法
-
要求:
① lambda的参数列表与返回值要求能够一 一对应lambda体中所引用方法的参数列表与返回值
② lambda的返回值要求与所引用方法的返回值保持对应一致
lambda的参数列表如果只有一个参数 :作为调用所引用的成员方法的对象存在
lambda的参数列表如果存在多个参数 :第一个参数作为调用所引用的成员方法的对象存在,lambda的第
二个参数开始,一 一对应匹配所引用方法的参数列表
package Thursday;
import java.io.PrintStream;
import java.sql.SQLOutput;
import java.util.Comparator;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
public class Test {
public static void main(String[] args) {
test();
test1();
test2();
}
// 类名 :: 实例方法
public static void test2(){
// BiPredicate<String,String> pre= (x,y)->x.equals(y);
BiPredicate<String,String> pre= String::equals;
System.out.println(pre.test(new String("wang"),"wee"));
}
// 类名 :: 静态方法
public static void test(){
// Comparator<Integer> sc=(x,y)->Integer.compare(x,y);
Comparator<Integer> sc=Integer::compare;
System.out.println(sc.compare(100,123));
}
// 对象 :: 实例方法
public static void test1(){
List<Integer> sd= List.of(1,2,3,4);
PrintStream ps=System.out;
// Consumer se=i->ps.println(i);
sd.forEach(System.out::println);
}
}
12.3 构造器引用
数据类型 :: new
package Thursday;
import java.util.function.Function;
import java.util.function.Supplier;
public class Test {
public static void main(String[] args) {
test();
}
public static void test(){
//lambda的参数列表匹配构造器的参数列表,lambda返回值就是所构建的对象--> 构造器引用
//Supplier<Employee> sup= ()->new Employee();
Supplier<Teacher> sup= Teacher::new;
System.out.println(sup.get());
//Function<String,Employee> fun = (s)->new Employee(s);
Function<String,Teacher> fun = Teacher::new;
System.out.println(fun.apply("zhangsan"));
}
}
12.4 Stream
Stream :
数据的渠道,用来操作由数据源(数组,集合)所产生的元素序列
IO :传输数据
Stream流 :操作数据,计算数据
数组|集合 :存储数据
-
特点:
1.Stream流本身不会存储数据2.Stream不会修改数据源|源对象,每次回返回持有结果的新的流Stream
3.延迟执行|惰性加载 :当获取终止行为时候,才会执行一系列的中间操作
4.流都是一次性的流,不能重复使用多次,一旦使用过就已经被破坏
-
步骤:
1.创建Stream 1)Collection->stream
2)Arrays->stream (数组)
3)Stream.of (值列表)
2.一系列流式的中间操作(都会返回一个持有结果的新的流)
3.终止行为
package Thursday;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Stream1 {
public static void main(String[] args) {
Stream<Integer> sc =List.of(1,2,3,4,5,6).stream();
sc.forEach(System.out::println);
String[] arr={"wang","chao","good"};
Stream<String> sd= Arrays.stream(arr);
sd.forEach(System.out::println);
Stream<Integer> se=Stream.of(5,4,3,2,1);
se.forEach(System.out::println);
}
}
12.5 中间操作
中间操作 :
1.过滤 Stream filter(Predicate<? super T> predicate);
2.去重 distinct() 比较equals与hashCode()
3.截取 limit(long) 从第一个开始截取几个
4.跳过 skip(long) 跳过前n个
5.排序 sorted() --> 内部比较器 sorted(Comparator) ->外部比较器
6.映射 map(Function fun) stream操作的每一个数据都所用于参数函数,映射成一个新的结果,最后返回一个持
有所有映射后的新的结果的流
package Thursday;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Middle {
public static void main(String[] args) {
List<Teacher> sc =Arrays.asList(
new Teacher("wangchao",22,22000),
new Teacher("changkun",22,20000),
new Teacher("zhaoshixiang",24,19000),
new Teacher("jishuai",23,21000),
new Teacher("jishuai",23,21000)
);
// 构建流
Stream<Teacher> st=sc.stream();
// 过滤
// st=st.filter(s->s.getAge()>22);
// 去重 限制 跳过
// st=st.distinct().limit(3).skip(1);
// 映射
// Stream<Integer> se=st.map(s->s.getAge());
// 排序
// ss=ss.sorted();
st=st.sorted((x,y)->Integer.compare(x.getAge(),y.getAge()));
// 终止行为
st.forEach(System.out::println);
}
}
12.6 终止行为
终止行为:
1.遍历 foreach(Consumer)
2.查找与匹配
// allMatch-检查是否匹配所有元素
// anyMatch-检查是否至少匹配一个元素
// noneMatch-检查是否没有匹配所有元素
// findFirst-返回第一个元素
// findAny-返回当前流中的任意元素
// count-返回流中元素的总个数
// max-返回流中最大值
// min-返回流中最小值
3.规约 reduce
map->reduce
加工->计算结果
4.收集
collect( )
package Thursday;
import jdk.swing.interop.SwingInterOpUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Middle {
public static void main(String[] args) {
List<Teacher> sc =Arrays.asList(
new Teacher("wangchao",22,22000),
new Teacher("changkun",22,20000),
new Teacher("zhaoshixiang",24,19000),
new Teacher("jishuai",23,21000),
new Teacher("jishuai",23,21000)
);
// 构建流
Stream<Teacher> st=sc.stream();
// System.out.println(st.distinct().allMatch(e->e.getAge()>20));
// Optional<Teacher> sb= st.sorted((x, y)->Double.compare(y.getSal(),x.getSal())).findFirst();
// System.out.println(sb.get());
// System.out.println(st.distinct().count());
// System.out.println(st.distinct().max((x,y)->Double.compare(y.getSal(),x.getSal())).get());
// System.out.println(st.map(x->x.getSal()).reduce((x,y)->x+y).get());
// 终止行为
// st.forEach(System.out::println);
// System.out.println(st.distinct().collect(Collectors.counting()));
// System.out.println(st.distinct().collect(Collectors.averagingDouble(Teacher::getSal)));
System.out.println(st.distinct().collect(Collectors.toMap(Teacher::getSal,Teacher::getAge)));
}
}
package Thursday;
import java.util.Objects;
public class Teacher implements Comparable<Teacher> {
private String name;
private int age;
private double sal;
public Teacher() {
}
public Teacher(String name, int age, double sal) {
this.name = name;
this.age = age;
this.sal = sal;
}
public Teacher(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", sal=" + sal +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return age == teacher.age && Double.compare(teacher.sal, sal) == 0 && Objects.equals(name, teacher.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, sal);
}
@Override
public int compareTo(Teacher o) {
return this.age-o.age;
}
}