邢台移动网站建设费用,dede仿网站目录,开网店的一年的费用,关于网站建设的方案ppt原来Lambda表达式是这样写的
lambda 是一个匿名函数#xff0c;我们可以把 lambda 表达式理解为是一段可以传递的代码。
lambda 简明地将代码或方法作为参数传递进去执行。
函数式编程#xff1a;核心是把函数作为值。
函数式接口 #xff1a;只有一个抽象方法的接口称之…原来Lambda表达式是这样写的
lambda 是一个匿名函数我们可以把 lambda 表达式理解为是一段可以传递的代码。
lambda 简明地将代码或方法作为参数传递进去执行。
函数式编程核心是把函数作为值。
函数式接口 只有一个抽象方法的接口称之为函数式接口。
函数式接口可以使用FunctionalInterface进行注解。
lambda表达式拆分为两部分 左侧lambda 表达式的参数列表 右侧lambda 表达式中所需要执行的功能即 lambda 体
Lambda 表达式非常方便在项目中一般在 stream 编程中用的比较多。
package com.lambda;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class Test1 {public static void main(String[] args) {ListStudent studentList new ArrayList();studentList.add(new Student(1, tom));studentList.add(new Student(2, marry));// Collectors.toMap的用法有很多MapInteger, String map studentList.stream().collect(Collectors.toMap(Student::getId, Student::getName));// {1tom, 2marry}System.out.println(map);}}class Student {private int id;private String name;public Student() {}public Student(int id, String name) {this.id id;this.name name;}public int getId() {return id;}public String getName() {return name;}public void setId(int id) {this.id id;}public void setName(String name) {this.name name;}
}理解一个 Lambda 表达式就三步 1、确认 Lambda 表达式的类型 2、找到要实现的方法 3、实现这个方法 就这三步没其他的了。
1、确认 Lambda 表达式的类型
能用 Lambda 表达式来表示的类型必须是一个函数式接口而函数式接口就是只有一个抽象方法的接口。
例如 JDK 中 Runnable 接口
FunctionalInterface
public interface Runnable {public abstract void run();
}这就是一个标准的函数式接口因为只有一个抽象方法而且这个接口上有个注解 FunctionalInterface。
这个仅仅是在编译期帮你检查你这个接口是否符合函数式接口的条件比如你没有任何抽象方法或者有多个抽象
方法编译是无法通过的。
再稍稍复杂一点Java 8 之后接口中是允许使用默认方法和静态方法的而这些都不算抽象方法所以也可以加在
函数式接口里。看看你可能不太熟悉又有点似曾相识的一个接口。
FunctionalInterface
public interface ConsumerT {void accept(T t);default ConsumerT andThen(Consumer? super T after) {}
}只有一个抽象方法还有一个默认方法(方法体的代码省略了)这个也不影响它是个函数式接口。再看一个更复杂
的多了静态方法这同样也是个函数式接口因为它仍然只有一个抽象方法。
FunctionalInterface
public interface PredicateT {boolean test(T t);default PredicateT and(Predicate? super T other) {...}default PredicateT negate() {...}default PredicateT or(Predicate? super T other) {...}static T PredicateT isEqual(Object targetRef) {...}static T PredicateT not(Predicate? super T target) {...}
}先不用管这些方法都是干嘛的这些类在 Stream 设计的方法中比比皆是我们就先记住这么一句话Lambda表
达式需要的类型为函数式接口函数式接口里只有一个抽象方法就够了以上三个例子都属于函数式接口。
2、找到要实现的方法
Lambda 表达式就是实现一个方法什么方法呢就是刚刚那些函数式接口中的抽象方法。
那就太简单了因为函数式接口有且只有一个抽象方法找到它就行了。我们尝试把刚刚那几个函数式接口的抽象
方法找到。
FunctionalInterface
public interface Runnable {public abstract void run();
}FunctionalInterface
public interface ConsumerT {void accept(T t);default ConsumerT andThen(Consumer? super T after) {...}
}FunctionalInterface
public interface PredicateT {boolean test(T t);default PredicateT and(Predicate? super T other) {...}default PredicateT negate() {...}default PredicateT or(Predicate? super T other) {...}static T PredicateT isEqual(Object targetRef) {...}static T PredicateT not(Predicate? super T target) {...}
}3、实现这个方法
Lambda 表达式就是要实现这个抽象方法如果不用 Lambda 表达式你一定知道用匿名类如何去实现吧比如
我们实现刚刚 Predicate 接口的匿名类。
PredicateString predicate new PredicateString() {Overridepublic boolean test(String s) {return s.length() ! 0;}
};3.1 单个入参
那如果换成 Lambda 表达式呢就像这样。
PredicateString predicate (String s) - {return s.length() ! 0;
};看出来了么这个 Lambda 语法由三部分组成 1、参数块就是前面的 (String s)就是简单地把要实现的抽象方法的参数原封不动写在这。 2、小箭头就是 - 这个符号。 3、代码块就是要实现的方法原封不动写在这。 首先看参数快部分(String s) 里面的类型信息是多余的因为完全可以由编译器推导去掉它。
注意lambda 表达式的参数类型可以省略不写因为 jvm 编译器可以从上下文推断出数据类型。
即“类型推断”如果要在参数里面写数据类型都要写上。
PredicateString predicate (s) - {return s.length() ! 0;
};当只有一个参数时括号也可以去掉。
PredicateString predicate s - {return s.length() !0;
};再看代码块部分方法体中只有一行代码可以把花括号和 return 关键字都去掉。
PredicateString p s - s.length() ! 0;3.2 无入参
来再让我们实现一个 Runnable 接口。
FunctionalInterface
public interface Runnable {public abstract void run();
}Runnable r () - System.out.println(I am running);你看这个方法没有入参所以前面括号里的参数就没有了这种情况下括号就不能省略。
通常我们快速新建一个线程并启动时是不是像如下的写法熟悉吧
new Thread(() - System.out.println(I am running)).start();3.3 多个入参
之前我们只尝试了一个入参接下来我们看看多个入参的。
FunctionalInterface
public interface BiConsumerT, U {void accept(T t, U u);
}然后看看一个用法是不是一目了然。
BiConsumerRandom, Integer randomNumberPrinter (random, number) - {for (int i 0; i number; i) {System.out.println(next random random.nextInt());}
};
randomNumberPrinter.accept(new Random(314L), 5);3.4 带返回值
刚刚只是多个入参那我们再加个返回值
FunctionalInterface
public interface BiFunctionT, U, R {R apply(T t, U u);
}BiFunctionString, String, Integer findWordInSentence (word, sentence) - sentence.indexOf(word);
Integer result findWordInSentence.apply(e,hello);
// 1
System.out.println(result);4、四大核心函数式接口
其实函数式接口里那个抽象方法无非就是入参的个数以及返回值的类型。入参的个数可以是一个或者两个返
回值可以是 void或者 boolean或者一个类型。那这些种情况的排列组合就是 JDK 给我们提供的
java.util.function 包下的类。
别看晕了我们分分类就好了。可以注意到很多类前缀是 IntLongDouble 之类的这其实是指定了入参的特
定类型而不再是一个可以由用户自定义的泛型比如说 DoubleFunction。
FunctionalInterface
public interface DoubleFunctionR {R apply(double value);
}这完全可以由更自由的函数式接口 Function 来实现。
FunctionalInterface
public interface FunctionT, R {R apply(T t);
}函数式接口几个简单分类就是 supplier: 没有入参有返回值。 function: 有入参有返回值。 consumer: 有入参无返回值。 predicate: 有入参返回 boolean 值。 Consumer: 消费性接口void accept(T t)。 Supplier: 共给性接口T get()。 FunctionT,R: 函数性接口T代表参数R代表返回值R apply(T t)。 Predicate: 断言性接口boolean test(T t)。 其实就是给我们提供了一个函数的模板区别仅仅是入参返参个数的排列组合。
package com.lambda;import java.util.function.Consumer;public class Test2 {public static void main(String[] args) {happy(10000, (money) - System.out.println(happy消费 money 元));}public static void happy(double money, ConsumerDouble con) {con.accept(money);}
}5、Stream编程
下面这段代码如果你项目中有用 stream 编程那肯定很熟悉有一个 Student 的 list你想把它转换成一个 map
key 是 student 对象的 idvalue 就是 student 对象本身。
package com.lambda;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class Test3 {public static void main(String[] args) {ListStudent studentList new ArrayList();studentList.add(new Student(1, tom));studentList.add(new Student(2, marry));// Collectors.toMap的用法有很多MapInteger, Student map studentList.stream().collect(Collectors.toMap(Student::getId, a - a, (a, b) - a));// {1com.lambda.Student2f4d3709, 2com.lambda.Student4e50df2e}System.out.println(map);}
}把 Lambda 表达式的部分提取出来。
Collectors.toMap(Student::getId, a - a, (a, b) - a)由于我们还没见过 :: 这种形式先打回原样这里只是让你预热一下。
Collectors.toMap(a - a.getId(), a - a, (a, b) - a)为什么它被写成这个样子呢我们看下 Collectors.toMap 这个方法的定义就明白了。
public static T, K, U
CollectorT, ?, MapK,U toMap(Function? super T, ? extends K keyMapper,Function? super T, ? extends U valueMapper,BinaryOperatorU mergeFunction) {return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}看入参有三个分别是 FunctionFunctionBinaryOperator其中 BinaryOperator 只是继承了 BiFunction
并扩展了几个方法我们没有用到所以不妨就把它当做 BiFunction。还记得 Function 和 BiFunction 吧
Function R apply(T t)
BiFunction R apply(T t, U u)第一个参数 a - a.getId() 就是 R apply(T t) 的实现入参是 Student 类型的对象 a返回 a.getId()。
第二个参数 a - a 也是 R apply(T t) 的实现入参是 Student 类型的 a返回 a 本身。
第三个参数 (a, b) - a 是 R apply(T t, U u) 的实现入参是Student 类型的 a 和 b返回是第一个入参 a
Stream 里把它用作当两个对象 a 和 b 的 key 相同时value 就取第一个元素 a其中第二个参数 a - a 在
Stream 里表示从 list 转为 map 时的 value 值就用原来的对象自己你肯定还见过这样的写法。
Collectors.toMap(a - a.getId(), Function.identity(), (a, b) - a)为什么可以这样写给你看 Function 类的全貌你就明白了。
FunctionalInterface
public interface FunctionT, R {R apply(T t);default V FunctionV, R compose(Function? super V, ? extends T before) {Objects.requireNonNull(before);return (V v) - apply(before.apply(v));}default V FunctionT, V andThen(Function? super R, ? extends V after) {Objects.requireNonNull(after);return (T t) - after.apply(apply(t));}static T FunctionT, T identity() {return t - t;}
}看到了吧identity 这个方法就是帮我们把表达式给实现了就不用我们自己写了其实就是包了个方法。这回
知道一个函数式接口为什么有好多还要包含一堆默认方法和静态方法了吧就是干这个事用的。
我们再来试一个Predicate 里面有这样一个默认方法 and。
FunctionalInterface
public interface PredicateT {boolean test(T t);default PredicateT and(Predicate? super T other) {Objects.requireNonNull(other);return (t) - test(t) other.test(t);}default PredicateT negate() {return (t) - !test(t);}default PredicateT or(Predicate? super T other) {Objects.requireNonNull(other);return (t) - test(t) || other.test(t);}static T PredicateT isEqual(Object targetRef) {return (null targetRef)? Objects::isNull: object - targetRef.equals(object);}
}它能干嘛用呢我来告诉你如果没有这个方法有一段代码你可能会这样写。
PredicateString p s - (s ! null) !s.isEmpty() s.length() 5;如果利用上这个方法就可以变成如下这种优雅形式。
PredicateString nonNull s - s ! null;
PredicateString nonEmpty s - s.isEmpty();
PredicateString shorterThan5 s - s.length() 5;
PredicateString p nonNull.and(nonEmpty).and(shorterThan5);6、Lambda方法引用
主要有三种语法格式 对象::实例方法名 类::静态方法名 类::实例方法名 那我们回过头再看刚刚的 Student::getId 这种写法。当方法体中只有一个方法调用时就可以作这样的简化。
比如这个 a - a.getId() 就只是对 Student 对象上 getId() 这个方法的调用那么就可以写成 Student::getId 这种形
式。
package com.lambda;import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;public class Test9 {public static void main(String[] args) {// 类::实例方法名FunctionUser, String n User::getName;FunctionUser, Integer a User::getAge;// 类::静态方法名FunctionString, String func1 User::concat2;SupplierString func2 User::getAddress;// 对象::实例方法名User user new User();FunctionString, String func3 user::concat1;SupplierString func4 user::getSchool;// 无参构造方法引用SupplierStudent supplier Student::new;Student student supplier.get();student.setName(tom);student.setId(10);// com.lambda.Student5b480cf9System.out.println(student);SupplierStudent supplier2 () - (new Student());Student student2 supplier2.get();student2.setName(tom);student2.setId(10);// com.lambda.Student723279cfSystem.out.println(student2);// 有参构造方法引用BiFunctionInteger, String, Student biFunction Student::new;Student stu biFunction.apply(11, marry);// com.lambda.Studentb4c966aSystem.out.println(stu);BiFunctionInteger, String, Student bf (id, name) - new Student(id, name);Student s bf.apply(12, john);// com.lambda.Student4e50df2eSystem.out.println(s);// 自定义有参构造函数StudentBuilder sb1 ((id, name) - new Student(id, name));Student s1 sb1.build(13, xm);// com.lambda.Student7cc355beSystem.out.println(s1);StudentBuilder sb2 Student::new;Student s2 sb2.build(14, xh);// com.lambda.Student12edcd21System.out.println(s2);// 自定义无参构造函数StudentBuilderNoArgs sb3 Student::new;Student s3 sb3.build();// com.lambda.Student5b6f7412System.out.println(s3);StudentBuilderNoArgs sb4 () - (new Student());Student s4 sb4.build();// com.lambda.Student312b1daeSystem.out.println(s4);}
}class User {private static int id;private String name;public static int getId() {return id;}public static void setId(int id) {User.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public String concat1(String str) {return str !;}public static String concat2(String str) {return str !;}public int getAge() {return 12;}public static String getAddress() {return 天津;}public String getSchool() {return 小学;}
}interface StudentBuilder {Student build(int id, String name);
}interface StudentBuilderNoArgs {Student build();
}再看几个例子
FunctionString, Integer toLength1 s - s.length();
FunctionString, Integer toLength2 String::length;
FunctionUser, String getName user - user.getName();
FunctionUser, String toLength User::getName;如果是构造方法的话也可以简化。
SupplierListString newListOfStrings1 () - new ArrayList();
SupplierListString newListOfStrings2 ArrayList::new;// ClassName::new
SupplierString sup () - new String();
SupplierString sup2 String::new;
String str sup.get();
String str2 sup2.get();
// false
System.out.println(str str2);// 对象::实例方法名
ConsumerString con (x) - System.out.println(x);
con.accept(hello);
ConsumerString con2 System.out::println;
con2.accept(world);// 类::静态方法名
ComparatorInteger com (x, y) - Integer.compare(x, y);
ComparatorInteger com2 Integer::compare;
System.out.println(com.compare(1, 2));
System.out.println(com2.compare(1, 2));// 类::实例方法名
BiPredicateString, String bp (x, y) - x.equals(y);
System.out.println(bp.test(a, a));
BiPredicateString, String bp2 String::equals;
System.out.println(bp2.test(a, a));7、Lambda例子
实例1
package com.lambda;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class Test6 {public static ListEmployee list Arrays.asList(new Employee(张三, 10, 1), new Employee(里斯, 20, 1), new Employee(王五, 16, 1), new Employee(二三, 30, 1));public static ListEmployee filterEmployee(ListEmployee list, MyPredicateEmployee mp) {ListEmployee emps new ArrayList();for (Employee employee : list) {if (mp.test(employee)) {emps.add(employee);}}return emps;}public static void main(String[] args) {test1();test2();}public static void test1() {//需要使用自定义的方法ListEmployee list2 filterEmployee(list, (e) - e.getAge() 15);list2.stream().map(Employee::getName).forEach(System.out::println);}public static void test2() {//可以使用stream进行list集合的过滤 不使用自定义接口ListEmployee list2 list.stream().filter((e) - e.getAge() 15).collect(Collectors.toList());list2.stream().map(Employee::getName).forEach(System.out::println);}
}class Employee {private String name;private int age;private double salary;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 getSalary() {return salary;}public void setSalary(double salary) {this.salary salary;}public Employee(String name, int age, double salary) {this.name name;this.age age;this.salary salary;}
}interface MyPredicateT {boolean test(T t);
}# 程序输出
里斯
王五
二三
里斯
王五
二三实例2
创建一个MyFun接口使用FunctionalInterface注解并创建一个抽象方法Integer getValue(Integer num);在
Test类对变量进行某种操作。
package com.lambda;FunctionalInterface
interface MyFun {Integer getValue(Integer num);
}public class Test7 {public static void test() {int a 10;System.out.println(a);a operation(a, num - num);System.out.println(a);}public static void main(String[] args) {test();}/*** param1 num : 传入的整形数* param2 mf : 实现某种方式对 整形数 进行操作。**/public static Integer operation(Integer num, MyFun mf) {return mf.getValue(num);}
}# 程序输出
10
11package com.lambda;import java.util.Arrays;
import java.util.Collections;
import java.util.List;public class Test8 {public static ListEmployee list Arrays.asList(new Employee(张三, 10, 1),new Employee(里斯, 20, 1),new Employee(王五, 16, 1),new Employee(二三, 30, 1));public static void test() {Collections.sort(list, (e1, e2) - {if (e1.getAge() e2.getAge()) {return e1.getName().compareTo(e2.getName());} else {//比较年龄大小return Integer.compare(e1.getAge(), e2.getAge());}});for (Employee e : list) {System.out.println(e);}}public static void main(String[] args) {test();}
}# 程序输出
com.lambda.Employee404b9385
com.lambda.Employee6d311334
com.lambda.Employee682a0b20
com.lambda.Employee3d075dc0