Java的Lambda表达式和函数式接口

Lambda表达式

简介

Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的 代码(将代码像数据一样进行传递)。可以替换匿名内部类,函数式接口。

Lambda 是jdk1.8后有的。

例如:匿名内部类  VS   Lambda表达式

//原来使用匿名内部类
TreeSet<Person> ts = new TreeSet<Person>(new Comparator<Person>() {
	@Override
	public int compare(Person o1, Person o2) {
		return o1.getName().compareTo(o2.getName());
	}
});
//JDK1.8后可以使用Lambda
Comparator<Person> com = (x,y)->x.getName().compareTo(y.getName());
TreeSet<Person> ts2 = new TreeSet<Person>(com);

 

//匿名内部类                                           
Runnable r1 = new Runnable() {                    
	@Override                                     
	public void run() {                           
		System.out.println("run...");             
	}                                             
};                                                
//Lambda表达式                                       
Runnable r2 = () -> System.out.println("run..."); 

语法

Lambda表达式:Java8以后,引入了“->”操作符
    “->”左侧:参数列表
    “->”右侧:所需要执行的功能,即Lambda体

语法格式一:无参数无返回值
	()-> System.out.println("Hello Lambda ");
语法格式二: 一个参数,无返回
	//x表示变量,变量名x任意
	(x) -> System.out.println(x);
	//只有一个参数时,()可以省略
	x -> System.out.println(x);
语法格式三:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
	Comparator<Integer> com = (x, y) -> {
		System.out.println("函数式接口");
		return Integer.compare(x, y);
	};
语法格式四:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);

语法格式五:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
		(Integer x, Integer y) -> Integer.compare(x, y);

 

 函数式接口

只包含一个抽象方法的接口,称为 函数式接口。
你可以通过 Lambda 表达式来创建该接口的对象。
可以在任意接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

自定义函数式接口

@FunctionalInterface
public interface MyFun {
	public Integer getValue(Integer num);
}
@FunctionalInterface
public interface Myfunc<T> {
	public T getValue(T t);
}

作为参数传递 Lambda  表达式,实参即Lambda表达式必须与函数接口的参数一致

@Test
public void test07() {
	String s = toOperateString((x) -> x.toUpperCase(), "goodman");
	System.out.println(s);
	String s2 = toOperateString((x)->x.toLowerCase(), s);
	System.out.println(s2);
}

//测试 作为参数传递 Lambda 表达式
public String toOperateString(Myfunc<String> fun, String origin) {
	String res = fun.getValue(origin);
	return res;
}

 

内置的函数式接口

Java8 内置的四大核心函数式接口      
                        
Consumer<T> : 消费型接口     
        void accept(T t);  
                        
Supplier<T> : 供给型接口     
        T get();           
                        
Function<T, R> : 函数型接口  
        R apply(T t);      
                        
Predicate<T> : 断言型接口    
        boolean test(T t);

 

其他类型的一些函数式接口
  除了上述得4种类型得接口外还有其他的一些接口供我们使用:
    1)BiFunction<T, U, R>
      参数类型有2个,为T,U,返回值为R,其中方法为 R apply(T t, U u)
    2)UnaryOperator<T>(Function子接口)
      参数为T,对参数为T的对象进行一元操作,并返回T类型结果,其中方法为 T apply(T t)
    3)BinaryOperator<T>(BiFunction子接口)
      参数为T,对参数为T得对象进行二元操作,并返回T类型得结果,其中方法为 T apply(T t1, T t2)
    4)BiConsumer(T, U)
      参数为T,U  无返回值,其中方法为 void accept(T t, U u)
    5)ToIntFunction<T>、ToLongFunction<T>、ToDoubleFunction<T>
      参数类型为T,返回值分别为int,long,double,分别计算int,long,double得函数。
    6)IntFunction<R>、LongFunction<R>、DoubleFunction<R>
      参数分别为int,long,double,返回值为R。

 

方法引用和构造器引用

方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况 :
  对象 :: 实例方法
  类 :: 静态方法
  类 :: 实例方法

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。

Consumer con = (x) -> System.out.println(x);
//等价于
Consumer con2 = System.out::println;

BinaryOperator<Double> bo = (x,y) -> Math.pow(x, y);
//等价于
BinaryOperator<Double> bo2 = Math::pow;

注意:实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!

 

构造器引用

格式:      类名::new

Function<Integer, MyClass> fun = (x) -> new MyClass(x);
//等价于
Function<Integer, MyClass> fun2 = MyClass::new;

 数组

Function<Integer, Integer[]> fun = (x) -> new Integer[x];
//等价于
Function<Integer, Integer[]> fun2 = Integer[]::new;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

********************************

posted @ 2021-09-10 18:14  htj10  阅读(121)  评论(0编辑  收藏  举报
TOP