lambda简介
lambda表达式是java8中的一个重要的特性,允许通过表达式来代替功能接口。lambda和方法一样,提供了一个正常的参数列表和一个使用这些参数的主体,主体可以是一个表达式或一个代码块。lambda可以看做是一个匿名内部类的语法糖,也可以称为闭包。
优点:
- 代码简洁,开发迅速
- 方便函数式编程
- 过滤和计算非常容易
- 改善了集合类的操作
缺点:
- 代码可读性差
- 不容易进行调试
- 在非并行计算中,一些计算未必有传统的for循环性能高
语法
(parameters)-> expression 表达式
(parameters)->{statements;} 语句块
由三个部分组成:
-
parameters:类似方法中的形参列表,这里的参数是接口里的参数,可以明确声明,也可以不声明,类型由jvm推断
-
-> 可翻译为被用于的意思
-
方法体:可以是表达式,也可以是代码块。代码块可以返回一个值,也可以不返回一个值,此处代码块相当于接口的实现的方法体
函数式接口
定义:一个接口中有且只有一个抽象方法
注解校验接口是否是函数式接口
public class Test {
public static void main(String[] args) {
//无参 无返回值,只有一行语句
MyInter inter = () -> System.out.println("hello");
//无参,无返回值,有多行语句
MyInter1 inter1 = () -> {
System.out.println("hello");
System.out.println("hello");
};
//有一个参数没有返回值,只有一行语句
// MyInter2<String> inter2 = (String x) ->{
// System.out.println(x);
// };
MyInter2<String> inter2 = x->System.out.println(x);
// MyInter2<String> inter2 = System.out::println;
//有一个参数,有返回值,只有一行语句:右侧大括号和return可省略
MyInter3<Integer> inter3 = x -> Math.abs(x);
//有两个或以上参数,有返回值
MyInter4 inter4 = (x,y) -> (int) Math.pow(x,y);
MyInter4 inter41 = (x,y) -> {
int sum =1;
for (int i = 0; i <= y; i++) {
sum *=x;
}
return sum;
};
}
}
interface MyInter {
void test();
}
interface MyInter1 {
void test();
}
interface MyInter2 <T>{
void test(T t);
}
interface MyInter3 <T>{
Integer abs(T t);
}
interface MyInter4 {
int pow(int x,int y);
}
四个核心函数式接口
接口名 | 类型 | 抽象方法 |
---|---|---|
Consumer | 消费型接口 | void accept(T t); |
Supplier | 供给型接口 | T get(); |
Function<T,R> | 函数型接口 | R apply(T t); |
Predicate | 断言型接口 | boolean test( T t); |
其他函数式接口
-
Consumer
public static void main(String[] args) { demo(); } public static void demo(){ //接收一个参数,没有返回值 Consumer consumer = (X) -> System.out.println("hello"); consumer.accept(12); }
-
Supplier
可以生产一个需要的数据,又不需要提供参数,就可以使用供给型接口
public static void main(String[] args) { Supplier<String> supplier = () -> { Random random = new Random(); String code= ""; for (int i = 0; i < 4; i++) { int x = random.nextInt(10); code += x; } return code; }; List<String> codelist = getCode(10,supplier); System.out.println(codelist); } /** * 获取代码 * * @param x 生成几个随机数验证码 * @param supplier 供应商 * @return {@link List}<{@link String}> */ public static List<String> getCode(int x, Supplier<String> supplier){ List<String> list = new ArrayList<>(x); for (int i = 0; i < x; i++) { list.add(supplier.get());//get()可以返回任意类型 } return list; } }
-
Function
需要在一个方法中。传入参数,获取一个返回值,可以使用函数型接口
public static void main(String[] args) { // Function<Double, Double> function = (x) -> { // return (int) (x * 100 + 0.5) / 100D; // }; Function<Double,Double> function = x -> (int) (x * 100 + 0.5) / 100D;//保留两位小数操作 System.out.println(k2(3.1415, function)); } public static double k2(double i, Function<Double, Double> function) { return function.apply(i); }
-
Predicate
在方法中传一个参数,方法进行判断,返回boolean类型的值,需要使用断言型接口
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("123"); list.add("143"); list.add("123"); list.add("133"); list.add("123"); Predicate<String> predicate = x -> x.equals("123"); List<String> filter = filter(list, predicate); for (String s : filter) { System.out.println(s); } } public static List<String> filter(List<String> list, Predicate<String> predicate){ List<String> list1 = new ArrayList<>(); for (String s : list) { boolean test = predicate.test(s); if (test){ list1.add(s); } } return list1; }
方法引用
如果lambda表达式体中的功能 有方法已经实现了,则可以使用方法引用
lambda表达式体中调用方法的参数列表和返回值,要和函数式接口中定义的抽象方法参数列表和返 回值一致。
语法格式:
静态方法引用: 类名:: 静态方法名
实例方法引用: 实例对象名:: 实例方法名
特殊方法引用: 类名:: 实例方法名
构造方法引用: 类名:: new
-
静态方法引用
public static void main(String[] args) { List<Integer> list = Arrays.asList(12,32,15,6,78,25); // list.sort(new Comparator<Integer>() { // @Override // public int compare(Integer o1, Integer o2) { // return Integer.compare(o1,o2); // } // }); // list.sort(( o1, o2)-> Integer.compare(o1,o2)); // System.out.println(list); //静态方法引用 list.sort(Integer::compare); System.out.println(list); }
-
实例方法引用
public class Test { public static void main(String[] args) { /*List<Integer> list= Arrays.asList(12,32,15,6,78,25); //list.sort((o1, o2)->Integer.compare(o1,o2)); list.sort(Integer::compare); System.out.println(list);*/ // Consumer<String> consumer=X::test; //X x = new X(); //Supplier<Integer> supplier = new X()::random; List<Integer> list= Arrays.asList(12,32,15,6,78,25); list.forEach(System.out::println); } } class X { public static void test(String x) { System.out.println(x); } public int random() { Random r = new Random(); return r.nextInt(10); } }
-
特殊方法引用
public class Test1 { public static void main(String[] args) { //当我们函数中有参数,第一个参数来调用方法,可以使用特殊方法引用 /* String s="abc"; Function<String,String> f=String::toUpperCase; System.out.println(f.apply(s));*/ BiPredicate<String, String> predicate = String::equals; System.out.println(predicate.test("abc","abc")); } }
-
构造方法引用
调用的构造方法的参数列表和函数式接口中抽象方法的参数列表一致
public class Test2 { public static void main(String[] args) { // Supplier<Teacher> supplier=Teacher::new; // System.out.println(supplier.get()); /* Function<String,Teacher> function=Teacher::new; System.out.println(function.apply("李白"));*/ BiFunction<String,Integer,Teacher> function=Teacher::new; System.out.println(function.apply("李白",20)); } } class Teacher{ private String name; private Integer age; public Teacher() { System.out.println("无参构造方法"); } public Teacher(String name){ this.name=name; System.out.println("有一个参数的构造方法"); } public Teacher(String name, Integer age) { this.name = name; this.age = age; System.out.println("有两个参数的构造方法"); } @Override public String toString() { return "Teacher{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
-
数组引用
数组类型[]::new
public class Test3 { public static void main(String[] args) { // Function<Integer,Integer[]> function=x->new Integer[x]; Function<Integer,Integer[]> function= Integer[]::new; Integer[] apply = function.apply(10); Arrays.fill(apply,10); System.out.println(Arrays.toString(apply)); System.out.println(apply.length); } }
-
this 和 super引用方式
class XX{ public void test1(String str){ } public void test2(String str){ //Consumer<String> consumer=s->test1(s); Consumer<String> consumer=this::test1; } } class YY extends XX{ public void test(String str){ //Consumer<String> consumer=s->test1(s); Consumer<String> consumer=super::test1; } }